Skip to content

Commit 52bde9e

Browse files
committed
refactored read_data function
1 parent f01638a commit 52bde9e

File tree

1 file changed

+98
-58
lines changed

1 file changed

+98
-58
lines changed

R/read.R

Lines changed: 98 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -78,23 +78,22 @@ read_keyvalue <- function(drfile, sheet, ranges, translate = FALSE, translations
7878
#' @noRd
7979
#'
8080
read_table <- function(drfile, sheet, ranges, translate = FALSE, translations = NULL, atomicclass = "character", ...) {
81+
# Read and combine data from the specified ranges
8182
tbl <- lapply(ranges, function(range) {
82-
readxl::read_excel(drfile, sheet = sheet, range = range)}) |>
83-
dplyr::bind_rows()
83+
readxl::read_excel(drfile, sheet = sheet, range = range)
84+
}) |> dplyr::bind_rows()
8485

86+
# Coerce columns to the specified atomic class
8587
if (length(atomicclass) == 1) {
86-
for (i in seq_along(tbl)) {
87-
tbl[[i]] <- tbl[[i]] |> coerce(atomicclass)
88-
}
88+
tbl[] <- lapply(tbl, coerce, atomicclass)
8989
} else {
90-
if (!length(atomicclass) == ncol(tbl)) {
90+
if (length(atomicclass) != ncol(tbl)) {
9191
rlang::abort("The number of atomic classes must be 1 or equal to the number of columns in the table.")
9292
}
93-
for (i in seq_along(atomicclass)) {
94-
tbl[[i]] <- tbl[[i]] |> coerce(atomicclass[i])
95-
}
93+
tbl[] <- Map(coerce, tbl, atomicclass)
9694
}
9795

96+
# Translate column names if required
9897
if (translate) {
9998
names(tbl) <- long_to_shortnames(names(tbl), translations)
10099
}
@@ -187,80 +186,121 @@ short_to_longnames <- function(v, translations) {
187186
#' @export
188187
#'
189188
read_data <- function(drfile, guide, checkname = FALSE) {
190-
189+
# Load the guide if it's a file path
191190
if (inherits(guide, "character")) {
192-
# If 'guide' is a file path then read the guide
193191
guide <- read_guide(guide)
194-
} else {
195-
if (! inherits(guide, "guide")) {
196-
cl <- class(guide)
197-
rlang::abort(glue::glue("The guide must be a path (character) to a guide file or a reporting template guide object (guide object), not an object of class {cl}."))
198-
}
192+
} else if (!inherits(guide, "guide")) {
193+
rlang::abort(glue::glue(
194+
"The guide must be a path (character) to a guide file or a reporting template guide object (guide object), not an object of class {class(guide)}."
195+
))
199196
}
200197

201198
result <- list()
202199

200+
# Process each location in the guide
203201
for (location in guide$locations) {
204202
read_function <- switch(
205203
location$type,
206204
"keyvalue" = read_keyvalue,
207205
"table" = read_table,
208-
"platedata" = read_key_plate
206+
"platedata" = read_key_plate,
207+
"cells" = read_cells,
208+
rlang::abort(glue::glue("Unsupported location type: {location$type}"))
209209
)
210210

211-
atomicclass <- if ("atomicclass" %in% names(location)) location$atomicclass else "character"
212-
213-
if (!location$type == "cells") {
214-
chunk <- read_function(drfile = drfile, sheet = location$sheet, ranges = location$ranges,
215-
translate = location$translate, translations = guide$translations,
216-
atomicclass = atomicclass)
217-
} else {
218-
chunk <- read_cells(drfile = drfile, sheet = location$sheet, variables = location$variables, translate = location$translate,
219-
translations = guide$translations, atomicclass = atomicclass)
220-
}
211+
atomicclass <- location$atomicclass %||% "character"
221212

222-
if (!(location$varname %in% names(result[[location$type]]))) {
223-
result[[location$type]][[location$varname]] <- chunk
213+
# Read data using the appropriate function
214+
chunk <- if (location$type == "cells") {
215+
read_function(
216+
drfile = drfile,
217+
sheet = location$sheet,
218+
variables = location$variables,
219+
translate = location$translate,
220+
translations = guide$translations,
221+
atomicclass = atomicclass
222+
)
224223
} else {
225-
result[[location$type]][[location$varname]] <- switch(
226-
location$type,
227-
"keyvalue" = c(result[[location$type]][[location$varname]], chunk),
228-
"table" = dplyr::bind_rows(result[[location$type]][[location$varname]], chunk),
229-
"platedata" = suppressMessages(dplyr::full_join(result[[location$type]][[location$varname]], chunk)),
230-
"cells" = c(result[[location$type]][[location$varname]], chunk),
224+
read_function(
225+
drfile = drfile,
226+
sheet = location$sheet,
227+
ranges = location$ranges,
228+
translate = location$translate,
229+
translations = guide$translations,
230+
atomicclass = atomicclass
231231
)
232232
}
233+
234+
# Combine results
235+
result[[location$type]][[location$varname]] <- combine_results(
236+
result[[location$type]][[location$varname]],
237+
chunk,
238+
location$type
239+
)
233240
}
234241

235-
template.version <- result$cells$.template$version
236-
if (grepl("^\\d+$", template.version)) {
237-
template.version <- paste0(template.version, ".0")
238-
rlang::warn(glue::glue("Incorrectly formatted template version number '{result$cells$.template$version}'. Version
239-
numbers must have a minor number. Will interpret '{result$cells$.template$version}' as '{template.version}'."))
242+
# Validate template version
243+
validate_template_version(result$cells$.template$version, guide)
244+
245+
# Check template name if required
246+
if (checkname && guide$template.name != result$template.metadata$template.name) {
247+
rlang::abort(glue::glue(
248+
"The name of the guide ({guide$template.name}) does not match the name of the excel template ({result$template.metadata$template.name})."
249+
))
240250
}
241-
num.template.version <- package_version(template.version)
242-
num.min.version <- package_version(guide$template.min.version)
243251

244-
if (num.template.version < num.min.version) {
245-
rlang::abort(glue::glue("The guide is incompatible with the template.
246-
The template version should be minimally {guide$template.min.version}, whereas it is {result$template.metadata$template.version}."))
252+
result$.sourcefile <- drfile
253+
result$.guide <- guide
254+
result
255+
}
256+
257+
#' Helper function to combine results based on location type
258+
#' @param existing The existing data
259+
#' @param chunk The new data
260+
#' @param type The location type
261+
#' @noRd
262+
combine_results <- function(existing, chunk, type) {
263+
if (is.null(existing)) {
264+
return(chunk)
247265
}
248266

249-
if (!is.null(guide$template.max.version)) {
250-
num.max.version <- package_version(guide$template.max.version)
251-
if (num.max.version < num.template.version) {
252-
rlang::abort(glue::glue("The guide is incompatible with the template.
253-
The template version should be maximally {guide$template.max.version}, whereas it is {result$template.metadata$template.version}."))
254-
}
267+
switch(
268+
type,
269+
"keyvalue" = c(existing, chunk),
270+
"table" = dplyr::bind_rows(existing, chunk),
271+
"platedata" = suppressMessages(dplyr::full_join(existing, chunk)),
272+
"cells" = c(existing, chunk),
273+
rlang::abort(glue::glue("Unsupported location type for combining results: {type}"))
274+
)
275+
}
276+
277+
#' Helper function to validate template
278+
#' @param template_version The version of the template
279+
#' @param guide The guide object
280+
#' @noRd
281+
validate_template_version <- function(template_version, guide) {
282+
if (grepl("^\\d+$", template_version)) {
283+
template_version <- paste0(template_version, ".0")
284+
rlang::warn(glue::glue(
285+
"Incorrectly formatted template version number '{template_version}'. Version numbers must have a minor number. Interpreting as '{template_version}'."
286+
))
255287
}
256288

257-
if (checkname) {
258-
if (guide$template.name != result$template.metadata$template.name) {
259-
rlang::abort(glue::glue("The name of the guide ({guide$template.name}) does not match the name of the excel template ({result$template.metadata$template.name})."))
260-
}
289+
num_template_version <- package_version(template_version)
290+
num_min_version <- package_version(guide$template.min.version)
291+
292+
if (num_template_version < num_min_version) {
293+
rlang::abort(glue::glue(
294+
"The guide is incompatible with the template. The template version should be at least {guide$template.min.version}, but it is {template_version}."
295+
))
261296
}
262297

263-
result$.sourcefile <- drfile
264-
result$.guide <- guide
265-
result
298+
if (!is.null(guide$template.max.version)) {
299+
num_max_version <- package_version(guide$template.max.version)
300+
if (num_template_version > num_max_version) {
301+
rlang::abort(glue::glue(
302+
"The guide is incompatible with the template. The template version should be at most {guide$template.max.version}, but it is {template_version}."
303+
))
304+
}
305+
}
266306
}

0 commit comments

Comments
 (0)