Skip to content

The 'd' in [red] is interpreted as a date format #388

Description

@nacnudus

readxl/src/ColSpec.h

Lines 145 to 148 in 0d9ad4f

// TO FIX? So far no bug reports due to this.
// Logic below is too simple. For example, it deems this format string a date:
// "$"#,##0_);[Red]\("$"#,##0\)
// because of the `d` in `[Red]`

That was too tempting for somebody, who created this beauty (see MedicareAndLevies!Q:Q ):

How to fix?

// Ideally this can wait until we are using something like

... like the awful hack in tidyxl? 😉

// Adapted from hadley/readxl
bool styles::isDateFormat(std::string formatCode) {
  for (size_t i = 0; i < formatCode.size(); ++i) {
    switch (formatCode[i]) {
      case 'd':
        // Might be as in "[Red]"
        if (i < formatCode.size() - 1) {
          // there's at least one more character
          if (formatCode[i+1] == ']') {
            break;
          } else {
            return true;
          }
        }

Reprex:

library(tidyverse)
#> Loading tidyverse: ggplot2
#> Loading tidyverse: tibble
#> Loading tidyverse: tidyr
#> Loading tidyverse: readr
#> Loading tidyverse: purrr
#> Loading tidyverse: dplyr
#> Conflicts with tidy packages ----------------------------------------------
#> filter(): dplyr, stats
#> lag():    dplyr, stats
library(readxl)

source_url <- "https://github.com/tidyverse/readxl/files/1327821/CPS.v17-09-12.xlsx"
filename <- "CPS v17-09-12.xlsx"
sheetname <- "MedicareAndLevies"

download.file(source_url, filename, mode = "wb")

x <- read_xlsx(filename, sheetname, skip = 6)
class(x$MedLevSurRate2)
#> [1] "POSIXct" "POSIXt"

The culpable number formats:

library(tidyxl)
y <- tidy_xlsx(filename, sheetname) # Slow. I wish I could call Jim Hester for advice.

numFmt <- tibble(numFmt = y$formats$local$numFmt,
                 id = seq_along(y$formats$local$numFmt))

y$data[[1]] %>%
  filter(row >= 8, col == 17) %>%
  left_join(numFmt, by = c("local_format_id" = "id")) %>%
  distinct(numeric, numFmt)
#> # A tibble: 3 x 2
#>   numeric                               numFmt
#>     <dbl>                                <chr>
#> 1  0.0100     "#,##0.00_ ;[Red]\\-#,##0.00\\ "
#> 2  0.0125 "#,##0.0000_ ;[Red]\\-#,##0.0000\\ "
#> 3      NA                              General

Kudos to @HughParsonage for discovering this file and daring to import it into R.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugan unexpected problem or unintended behaviorformats 💅

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions