Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ URL: http://readxl.tidyverse.org,
BugReports: https://github.com/tidyverse/readxl/issues
Imports:
cellranger,
progress,
Rcpp (>= 0.12.18),
tibble (>= 1.3.1),
utils
Expand All @@ -55,6 +56,7 @@ Suggests:
rprojroot (>= 1.1),
testthat
LinkingTo:
progress,
Rcpp
VignetteBuilder:
knitr
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export(read_excel)
export(read_xls)
export(read_xlsx)
export(readxl_example)
export(readxl_progress)
importFrom(Rcpp,sourceCpp)
importFrom(cellranger,anchored)
importFrom(cellranger,cell_cols)
Expand Down
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ readxl exposes the `.name_repair` argument that is [coming to version 2.0.0 of t

## Other changes

* `read_excel()` and friends gain a `progress` argument that controls a progress spinner (#243, #538).

* `read_xls()` and `read_xlsx()` pass the `trim_ws` argument along (#514).

* readxl has a new article on reading Excel files with multiple header rows (#486, #492 @apreshill).
Expand Down
8 changes: 4 additions & 4 deletions R/RcppExports.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ xls_date_formats <- function(path) {
.Call(`_readxl_xls_date_formats`, path)
}

read_xls_ <- function(path, sheet_i, limits, shim, col_names, col_types, na, trim_ws, guess_max = 1000L) {
.Call(`_readxl_read_xls_`, path, sheet_i, limits, shim, col_names, col_types, na, trim_ws, guess_max)
read_xls_ <- function(path, sheet_i, limits, shim, col_names, col_types, na, trim_ws, guess_max = 1000L, progress = TRUE) {
.Call(`_readxl_read_xls_`, path, sheet_i, limits, shim, col_names, col_types, na, trim_ws, guess_max, progress)
}

xlsx_sheets <- function(path) {
Expand All @@ -29,8 +29,8 @@ parse_ref <- function(ref) {
.Call(`_readxl_parse_ref`, ref)
}

read_xlsx_ <- function(path, sheet_i, limits, shim, col_names, col_types, na, trim_ws, guess_max = 1000L) {
.Call(`_readxl_read_xlsx_`, path, sheet_i, limits, shim, col_names, col_types, na, trim_ws, guess_max)
read_xlsx_ <- function(path, sheet_i, limits, shim, col_names, col_types, na, trim_ws, guess_max = 1000L, progress = TRUE) {
.Call(`_readxl_read_xlsx_`, path, sheet_i, limits, shim, col_names, col_types, na, trim_ws, guess_max, progress)
}

zip_xml <- function(zip_path, file_path) {
Expand Down
20 changes: 20 additions & 0 deletions R/progress.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#' Determine whether to show progress spinner
#'
#' @description By default, readxl displays a progress spinner **unless**
#' one of the following is `TRUE`:
#' * The spinner is explicitly disabled by setting
#' `options(readxl.show_progress = FALSE)`.
#' * The code is run in a non-interactive session (`interactive()` is `FALSE`).
#' * The code is run by knitr / rmarkdown.
#' * The code is run in an RStudio notebook chunk.
#' readxl uses the [progress
#' package](https://cran.r-project.org/package=progress) under-the-hood and
#' therefore is also sensitive to any options that it consults.
#' @export
readxl_progress <- function() {
## based on readr:::show_progress()
isTRUE(getOption("readxl.show_progress", default = TRUE)) &&
interactive() &&
!isTRUE(getOption("knitr.in.progress")) &&
!isTRUE(getOption("rstudio.notebook.executing"))
}
15 changes: 14 additions & 1 deletion R/read_excel.R
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ NULL
#' the returned tibble. Ignored if `range` is given.
#' @param guess_max Maximum number of data rows to use for guessing column
#' types.
#' @param progress Display a progress spinner? By default, the spinner appears
#' only in an interactive session, outside the context of knitting a document,
#' and when the call is likely to run for several seconds or more. See
#' [readxl_progress()] for more details.
#' @param .name_repair Handling of column names. By default, readxl ensures
#' column names are not empty and are unique. If the tibble package version is
#' recent enough, there is full support for `.name_repair` as documented in
Expand Down Expand Up @@ -118,6 +122,7 @@ read_excel <- function(path, sheet = NULL, range = NULL,
col_names = TRUE, col_types = NULL,
na = "", trim_ws = TRUE, skip = 0, n_max = Inf,
guess_max = min(1000, n_max),
progress = readxl_progress(),
.name_repair = "unique") {
path <- check_file(path)
format <- check_format(path)
Expand All @@ -126,6 +131,7 @@ read_excel <- function(path, sheet = NULL, range = NULL,
col_names = col_names, col_types = col_types,
na = na, trim_ws = trim_ws, skip = skip,
n_max = n_max, guess_max = guess_max,
progress = progress,
.name_repair = .name_repair,
format = format
)
Expand All @@ -141,13 +147,15 @@ read_xls <- function(path, sheet = NULL, range = NULL,
col_names = TRUE, col_types = NULL,
na = "", trim_ws = TRUE, skip = 0, n_max = Inf,
guess_max = min(1000, n_max),
progress = readxl_progress(),
.name_repair = "unique") {
path <- check_file(path)
read_excel_(
path = path, sheet = sheet, range = range,
col_names = col_names, col_types = col_types,
na = na, trim_ws = trim_ws, skip = skip,
n_max = n_max, guess_max = guess_max,
progress = progress,
.name_repair = .name_repair,
format = "xls"
)
Expand All @@ -159,13 +167,15 @@ read_xlsx <- function(path, sheet = NULL, range = NULL,
col_names = TRUE, col_types = NULL,
na = "", trim_ws = TRUE, skip = 0, n_max = Inf,
guess_max = min(1000, n_max),
progress = readxl_progress(),
.name_repair = "unique") {
path <- check_file(path)
read_excel_(
path = path, sheet = sheet, range = range,
col_names = col_names, col_types = col_types,
na = na, trim_ws = trim_ws, skip = skip,
n_max = n_max, guess_max = guess_max,
progress = progress,
.name_repair = .name_repair,
format = "xlsx"
)
Expand All @@ -175,6 +185,7 @@ read_excel_ <- function(path, sheet = NULL, range = NULL,
col_names = TRUE, col_types = NULL,
na = "", trim_ws = TRUE, skip = 0, n_max = Inf,
guess_max = min(1000, n_max),
progress = readxl_progress(),
.name_repair = NULL,
format) {
if (format == "xls") {
Expand All @@ -192,12 +203,14 @@ read_excel_ <- function(path, sheet = NULL, range = NULL,
col_types <- check_col_types(col_types)
guess_max <- check_guess_max(guess_max)
trim_ws <- check_bool(trim_ws, "trim_ws")
progress <- check_bool(progress, "progress")
set_readxl_names(
read_fun(
path = enc2native(normalizePath(path)), sheet_i = sheet,
limits = limits, shim = shim,
col_names = col_names, col_types = col_types,
na = na, trim_ws = trim_ws, guess_max = guess_max
na = na, trim_ws = trim_ws, guess_max = guess_max,
progress = progress
),
.name_repair = .name_repair
)
Expand Down
14 changes: 11 additions & 3 deletions man/read_excel.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions man/readxl_progress.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 10 additions & 8 deletions src/RcppExports.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ BEGIN_RCPP
END_RCPP
}
// read_xls_
List read_xls_(std::string path, int sheet_i, IntegerVector limits, bool shim, RObject col_names, RObject col_types, std::vector<std::string> na, bool trim_ws, int guess_max);
RcppExport SEXP _readxl_read_xls_(SEXP pathSEXP, SEXP sheet_iSEXP, SEXP limitsSEXP, SEXP shimSEXP, SEXP col_namesSEXP, SEXP col_typesSEXP, SEXP naSEXP, SEXP trim_wsSEXP, SEXP guess_maxSEXP) {
List read_xls_(std::string path, int sheet_i, IntegerVector limits, bool shim, RObject col_names, RObject col_types, std::vector<std::string> na, bool trim_ws, int guess_max, bool progress);
RcppExport SEXP _readxl_read_xls_(SEXP pathSEXP, SEXP sheet_iSEXP, SEXP limitsSEXP, SEXP shimSEXP, SEXP col_namesSEXP, SEXP col_typesSEXP, SEXP naSEXP, SEXP trim_wsSEXP, SEXP guess_maxSEXP, SEXP progressSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Expand All @@ -42,7 +42,8 @@ BEGIN_RCPP
Rcpp::traits::input_parameter< std::vector<std::string> >::type na(naSEXP);
Rcpp::traits::input_parameter< bool >::type trim_ws(trim_wsSEXP);
Rcpp::traits::input_parameter< int >::type guess_max(guess_maxSEXP);
rcpp_result_gen = Rcpp::wrap(read_xls_(path, sheet_i, limits, shim, col_names, col_types, na, trim_ws, guess_max));
Rcpp::traits::input_parameter< bool >::type progress(progressSEXP);
rcpp_result_gen = Rcpp::wrap(read_xls_(path, sheet_i, limits, shim, col_names, col_types, na, trim_ws, guess_max, progress));
return rcpp_result_gen;
END_RCPP
}
Expand Down Expand Up @@ -91,8 +92,8 @@ BEGIN_RCPP
END_RCPP
}
// read_xlsx_
List read_xlsx_(std::string path, int sheet_i, IntegerVector limits, bool shim, RObject col_names, RObject col_types, std::vector<std::string> na, bool trim_ws, int guess_max);
RcppExport SEXP _readxl_read_xlsx_(SEXP pathSEXP, SEXP sheet_iSEXP, SEXP limitsSEXP, SEXP shimSEXP, SEXP col_namesSEXP, SEXP col_typesSEXP, SEXP naSEXP, SEXP trim_wsSEXP, SEXP guess_maxSEXP) {
List read_xlsx_(std::string path, int sheet_i, IntegerVector limits, bool shim, RObject col_names, RObject col_types, std::vector<std::string> na, bool trim_ws, int guess_max, bool progress);
RcppExport SEXP _readxl_read_xlsx_(SEXP pathSEXP, SEXP sheet_iSEXP, SEXP limitsSEXP, SEXP shimSEXP, SEXP col_namesSEXP, SEXP col_typesSEXP, SEXP naSEXP, SEXP trim_wsSEXP, SEXP guess_maxSEXP, SEXP progressSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Expand All @@ -105,7 +106,8 @@ BEGIN_RCPP
Rcpp::traits::input_parameter< std::vector<std::string> >::type na(naSEXP);
Rcpp::traits::input_parameter< bool >::type trim_ws(trim_wsSEXP);
Rcpp::traits::input_parameter< int >::type guess_max(guess_maxSEXP);
rcpp_result_gen = Rcpp::wrap(read_xlsx_(path, sheet_i, limits, shim, col_names, col_types, na, trim_ws, guess_max));
Rcpp::traits::input_parameter< bool >::type progress(progressSEXP);
rcpp_result_gen = Rcpp::wrap(read_xlsx_(path, sheet_i, limits, shim, col_names, col_types, na, trim_ws, guess_max, progress));
return rcpp_result_gen;
END_RCPP
}
Expand All @@ -124,12 +126,12 @@ END_RCPP
static const R_CallMethodDef CallEntries[] = {
{"_readxl_xls_sheets", (DL_FUNC) &_readxl_xls_sheets, 1},
{"_readxl_xls_date_formats", (DL_FUNC) &_readxl_xls_date_formats, 1},
{"_readxl_read_xls_", (DL_FUNC) &_readxl_read_xls_, 9},
{"_readxl_read_xls_", (DL_FUNC) &_readxl_read_xls_, 10},
{"_readxl_xlsx_sheets", (DL_FUNC) &_readxl_xlsx_sheets, 1},
{"_readxl_xlsx_strings", (DL_FUNC) &_readxl_xlsx_strings, 1},
{"_readxl_xlsx_date_formats", (DL_FUNC) &_readxl_xlsx_date_formats, 1},
{"_readxl_parse_ref", (DL_FUNC) &_readxl_parse_ref, 1},
{"_readxl_read_xlsx_", (DL_FUNC) &_readxl_read_xlsx_, 9},
{"_readxl_read_xlsx_", (DL_FUNC) &_readxl_read_xlsx_, 10},
{"_readxl_zip_xml", (DL_FUNC) &_readxl_zip_xml, 2},
{NULL, NULL, 0}
};
Expand Down
25 changes: 25 additions & 0 deletions src/Spinner.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#ifndef READXL_SPINNER_
#define READXL_SPINNER_

#include <RProgress.h>

class Spinner {
bool progress_;
RProgress::RProgress pb_;

public:
Spinner(bool progress = true):
progress_(progress)
{
if (progress_) {
pb_ = RProgress::RProgress(":spin");
pb_.set_total(1);
pb_.set_show_after(2);
}
}
void spin() { if (progress_) pb_.update(0.5); }
void finish() { if (progress_) pb_.update(1); }
~Spinner() { if (this->progress_) this->finish(); }
};

#endif
6 changes: 3 additions & 3 deletions src/XlsWorkSheet.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include <Rcpp.h>

#include "ColSpec.h"
#include "XlsWorkSheet.h"
#include <libxls/xls.h>
Expand All @@ -9,10 +8,11 @@ using namespace Rcpp;
List read_xls_(std::string path, int sheet_i,
IntegerVector limits, bool shim,
RObject col_names, RObject col_types,
std::vector<std::string> na, bool trim_ws, int guess_max = 1000) {
std::vector<std::string> na, bool trim_ws,
int guess_max = 1000, bool progress = true) {

// Construct worksheet ----------------------------------------------
XlsWorkSheet ws(path, sheet_i, limits, shim);
XlsWorkSheet ws(path, sheet_i, limits, shim, progress);

// catches empty sheets and sheets where requested rectangle contains no data
if (ws.nrow() == 0 && ws.ncol() == 0) {
Expand Down
Loading