A high-performance function for importing data from one or multiple Excel
files into data.table format, with fine-grained control over source
tracking columns, sheet selection, row skipping, and optional parallel
reading across (file, sheet) pairs.
Performance characteristics:
excel_sheets() called exactly once per file (cached).
The real cost of an Excel import is read_excel() parsing,
which is single-threaded C++ and not affected by the
data.table thread pool. The flat (file x sheet) task list is
therefore read in parallel across processes when
workers > 1: a fork pool on Unix/macOS, a PSOCK cluster on
Windows. The cluster / fork pool is always torn down on exit.
setDT() converts tibbles in-place — zero vector copies.
Tracking columns injected via := on small per-sheet tables
before the single final rbindlist.
The final rbindlist uses the ambient data.table thread
pool; tune it globally with setDTthreads if
needed. Workers are pinned to a single thread during the read phase
so parallel processes do not oversubscribe cores.
import_xlsx(
file,
rbind = TRUE,
sheet = NULL,
skip = 0L,
show_excel_name = TRUE,
show_sheet_name = TRUE,
workers = 1L,
verbose = FALSE,
...
)Non-empty character vector of paths to existing
.xlsx / .xls files.
logical(1). TRUE (default) binds all sheets
into a single data.table. FALSE returns a
flat named list keyed as "<filename>_<sheetname>".
Positive integer vector or NULL (default).
NULL imports every sheet. Indices must be valid
across all supplied files.
Non-negative integer(1). Number of rows to skip
before reading the header. Forwarded directly to
read_excel. Default 0L.
logical(1). When TRUE (default) and
rbind = TRUE, prepends an excel_name column
recording the source filename (extension stripped).
Silently ignored when rbind = FALSE (provenance is
already encoded in list-element names).
logical(1). When TRUE (default) and
rbind = TRUE, prepends a sheet_name column
recording the source sheet. Silently ignored when
rbind = FALSE.
integer(1). Number of parallel processes used to
read the (file x sheet) tasks. Default 1L (serial).
Values > 1 open a fork pool on Unix/macOS or a
PSOCK cluster on Windows; the pool is capped at the number
of tasks and always shut down on exit. Parallel reading
pays off when files are large or numerous; for many tiny
sheets the process / serialization overhead can dominate,
so leave this at 1L unless the import is heavy.
logical(1). When TRUE, print one
message() per sheet (source file, sheet name, and
row x col dimensions, with empty sheets flagged) followed
by a summary line. Default FALSE. Output is emitted
from the master process, so it surfaces identically in
serial and parallel modes.
Additional arguments forwarded to
read_excel (e.g. col_types,
na, trim_ws). Do not pass
path, sheet, or skip here; use the
dedicated parameters above.
rbind = TRUEA data.table. Tracking columns
excel_name and/or sheet_name are prepended when their
respective show_* flags are TRUE.
rbind = FALSEA named list of data.tables,
each element named "<filename>_<sheetname>". The list carries a
"source_files" attribute with the original file paths.
# Example: Excel file import demonstrations
# Setup test files
xlsx_files <- mintyr_example(
mintyr_examples("xlsx_test") # Get example Excel files
)
# Example 1: Import and combine all sheets from all files
import_xlsx(
xlsx_files, # Input Excel file paths
rbind = TRUE # Combine all sheets into one data.table
)
#> excel_name sheet_name col1 col2 col3
#> <char> <char> <num> <char> <lgcl>
#> 1: xlsx_test1 Sheet1 4 d FALSE
#> 2: xlsx_test1 Sheet1 5 f TRUE
#> 3: xlsx_test1 Sheet1 6 e TRUE
#> 4: xlsx_test1 Sheet2 1 a TRUE
#> 5: xlsx_test1 Sheet2 2 b FALSE
#> 6: xlsx_test1 Sheet2 3 c TRUE
#> 7: xlsx_test2 Sheet1 15 o FALSE
#> 8: xlsx_test2 Sheet1 16 p TRUE
#> 9: xlsx_test2 Sheet1 17 q FALSE
#> 10: xlsx_test2 a 7 g FALSE
#> 11: xlsx_test2 a 9 h TRUE
#> 12: xlsx_test2 a 8 i FALSE
#> 13: xlsx_test2 b 10 J FALSE
#> 14: xlsx_test2 b 11 K TRUE
#> 15: xlsx_test2 b 12 L FALSE
# Example 2: Import specific sheets separately
import_xlsx(
xlsx_files, # Input Excel file paths
rbind = FALSE, # Keep sheets as separate data.tables
sheet = 2 # Only import first sheet
)
#> $xlsx_test1_Sheet2
#> col1 col2 col3
#> <num> <char> <lgcl>
#> 1: 1 a TRUE
#> 2: 2 b FALSE
#> 3: 3 c TRUE
#>
#> $xlsx_test2_a
#> col1 col2 col3
#> <num> <char> <lgcl>
#> 1: 7 g FALSE
#> 2: 9 h TRUE
#> 3: 8 i FALSE
#>
#> attr(,"source_files")
#> [1] "/home/runner/work/_temp/Library/mintyr/extdata/xlsx_test1.xlsx"
#> [2] "/home/runner/work/_temp/Library/mintyr/extdata/xlsx_test2.xlsx"