From 9b20ae56bee87740467420ea85bee803d832fe58 Mon Sep 17 00:00:00 2001 From: Abel Vertesy Date: Sun, 30 Aug 2026 18:44:34 +0200 Subject: [PATCH 1/2] Fix undefined-variable crash and rewrite broken qs.2.table() read.simple.ssv() referenced `asTibble`, which wasn't a formal parameter (its sibling read.* functions have it) -- added it back. write.simple.xlsx()'s per-sheet assignRownames() helper used an external `df` instead of its own argument `x`, so every sheet was (re)built from the same data. qs.2.table() was non-functional on every branch: a single-colon `qs:qread` typo, a call to a non-existent `stringi::stri_detect`, and `base_filename`/`out_path` referenced without ever being defined. Rewrote it to actually read a .qs file and write it out as tsv/csv/csv2/excel. Co-Authored-By: Claude Sonnet 5 --- R/ReadWriter.R | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/R/ReadWriter.R b/R/ReadWriter.R index e9abbac..0b40682 100644 --- a/R/ReadWriter.R +++ b/R/ReadWriter.R @@ -442,6 +442,7 @@ read.simple.csv.named.vector <- function(file, sep = ";", col_names = FALSE, #' @param wRownames With row names? Default: TRUE. #' @param NaReplace Replace NA values? Default: TRUE. #' @param coltypes What type of variables are in columns? Auto-guessing can be very slow. Default: NULL. +#' @param asTibble Load as tibble or data frame? Default: FALSE (load as data frame). #' @examples #' \dontrun{ #' if (interactive()) { @@ -456,7 +457,7 @@ read.simple.csv.named.vector <- function(file, sep = ";", col_names = FALSE, #' @importFrom gtools na.replace read.simple.ssv <- function( ..., sep_ = " ", colnames = TRUE, wRownames = TRUE, NaReplace = TRUE, - coltypes = NULL + coltypes = NULL, asTibble = FALSE ) { pfn <- Stringendo::kollapse(...) # merge path and filename read_in <- suppressWarnings(readr::read_delim(pfn, delim = sep_, col_names = colnames, col_types = coltypes)) @@ -957,7 +958,7 @@ write.simple.xlsx <- function( # assign row names if required if (isFALSE(has_row_names)) { - assignRownames <- function(x) column.2.row.names(df, rowname_column = rowname_column, make_names = TRUE) + assignRownames <- function(x) column.2.row.names(x, rowname_column = rowname_column, make_names = TRUE) named_list <- lapply(named_list, assignRownames) message("Converting column ", rowname_column, " to row names: ", head(rownames(named_list[[1]]))) } @@ -1143,34 +1144,24 @@ write.simple.md.table <- function( qs.2.table <- function(path, out_file = c("tsv", "csv", "csv2", "excel")[1]) { # Ensure that the file exists and is a .qs file - stopifnot(file.exists(path), stringi::stri_detect(str = path, regex = "\\.qs$")) + stopifnot(file.exists(path), grepl("\\.qs$", path)) # Ensure out_file is one of the allowed choices out_file <- match.arg(out_file, c("tsv", "csv", "csv2", "excel")) # Read in the .qs file - data <- qs:qread(path) - - # Determine the output file extension and write the file based on the output format - path_out <- Stringendo::ppp(base_filename, out_file) + data <- qs::qread(path) - if (out_file == "excel") { - # out_path <- ppp(base_filename, "xlsx") - Stringendo::ppp(base_filename, out_file) - ReadWriter::write.simple.xlsx(data, out_path) - } + # Split into directory + base filename (without extension); write.simple.tsv()/ + # write.simple.xlsx() append the correct extension themselves. + out_dir <- dirname(path) + base_filename <- sub("\\.qs$", "", basename(path)) - if (out_file == "tsv") { - ReadWriter::write.simple.tsv(data, path_out, separator = "\t") - } else if (out_file == "csv") { - ReadWriter::write.simple.tsv(data, path_out, separator = ",") - } else if (out_file == "csv2") { - out_path <- paste0(base_filename, ".csv") - ReadWriter::write.simple.tsv(data, path_out, separator = ";") + if (out_file %in% c("tsv", "csv", "csv2")) { + sep <- switch(out_file, tsv = "\t", csv = ",", csv2 = ";") + ReadWriter::write.simple.tsv(data, manual_file_name = base_filename, manual_directory = out_dir, separator = sep) } else if (out_file == "excel") { - out_path <- paste0(base_filename, ".xlsx") - ReadWriter::write.simple.xlsx(data, out_path) + payload <- if (is.data.frame(data) || is.matrix(data)) list(data) else data + ReadWriter::write.simple.xlsx(payload, manual_file_name = base_filename, manual_directory = out_dir) } - - message("File saved as: ", out_path) } From 73fe9085d024f96e0e3cfd082a066720aa27834a Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Mon, 31 Aug 2026 17:24:57 +0000 Subject: [PATCH 2/2] Address Codex review: preserve row names, honor asTibble, sync Rd - write.simple.xlsx(): flip has_row_names to TRUE after converting a column to row names, so openxlsx actually writes them instead of silently dropping the identifier column. - read.simple.ssv(): only coerce to data.frame after NA-replacement when asTibble = FALSE, so asTibble is honored under the default NaReplace = TRUE. - Regenerate man/read.simple.ssv.Rd for the new asTibble parameter. Co-authored-by: Abel Vertesy <5101911+vertesy@users.noreply.github.com> --- R/ReadWriter.R | 6 +++++- man/read.simple.ssv.Rd | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/R/ReadWriter.R b/R/ReadWriter.R index 0b40682..eea0424 100644 --- a/R/ReadWriter.R +++ b/R/ReadWriter.R @@ -464,7 +464,10 @@ read.simple.ssv <- function( Stringendo::iprint("New variable dim: ", dim(read_in) - 0:1) if (wRownames) read_in <- column.2.row.names(read_in, as_df = !asTibble) - if (NaReplace) read_in <- as.data.frame(gtools::na.replace(read_in, replace = 0)) + if (NaReplace) { + read_in <- gtools::na.replace(read_in, replace = 0) + if (!asTibble) read_in <- as.data.frame(read_in) + } return(read_in) } @@ -961,6 +964,7 @@ write.simple.xlsx <- function( assignRownames <- function(x) column.2.row.names(x, rowname_column = rowname_column, make_names = TRUE) named_list <- lapply(named_list, assignRownames) message("Converting column ", rowname_column, " to row names: ", head(rownames(named_list[[1]]))) + has_row_names <- TRUE } FnP <- construct.file.path( diff --git a/man/read.simple.ssv.Rd b/man/read.simple.ssv.Rd index c812f30..6b78a65 100644 --- a/man/read.simple.ssv.Rd +++ b/man/read.simple.ssv.Rd @@ -10,7 +10,8 @@ read.simple.ssv( colnames = TRUE, wRownames = TRUE, NaReplace = TRUE, - coltypes = NULL + coltypes = NULL, + asTibble = FALSE ) } \arguments{ @@ -25,6 +26,8 @@ read.simple.ssv( \item{NaReplace}{Replace NA values? Default: TRUE.} \item{coltypes}{What type of variables are in columns? Auto-guessing can be very slow. Default: NULL.} + +\item{asTibble}{Load as tibble or data frame? Default: FALSE (load as data frame).} } \description{ Space separated values. Read in a file with Excel-style data: