Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] add wb_add_slicers #822

Merged
merged 9 commits into from Oct 22, 2023
Merged

[WIP] add wb_add_slicers #822

merged 9 commits into from Oct 22, 2023

Conversation

JanMarvin
Copy link
Owner

@JanMarvin JanMarvin commented Oct 19, 2023

Early draft.

  • Need to add the slicer variable to the wb$pivotDefinitions. If the variable is not available Excel in MS365 on Mac simply crashes.
  • can not yet add two slicers to a pivot table.
  • need a wb_add_slicer() function.
  • cannot yet select a condition (something like am = 1) : i currently wont add this
  • cannot modify the slicer columns/rows columnCount="3" style="SlicerStyleLight2"

Something like "draw the rest of the f**king owl" ... this works as intended

Update:

After some cleanup now both slicer and pivot table use pivot_table as argument and slicer for the variable used for slicing.

library(openxlsx2)

wb <- wb_workbook() %>%
  wb_add_worksheet() %>% wb_add_data(x = mtcars)

df <- wb_data(wb, sheet = 1)

wb$
  add_pivot_table(
    df, dims = "A3", slicer = "vs", rows = "cyl", cols = "gear", data = "disp",
    pivot_table = "mtcars"
  )$
  add_slicer(x = df, dims = "B7:D9", slicer = "vs", pivot_table = "mtcars",
             params = list(edit_as = "twoCell"))

if (interactive()) wb$open()
Screenshot 2023-10-20 at 19 51 36

@JanMarvin JanMarvin changed the title [slicer] create slicer items [WIP] add wb_add_slicers Oct 19, 2023
@JanMarvin JanMarvin added the enhancement 😀 New feature or request label Oct 19, 2023
@JanMarvin JanMarvin added this to the future milestone Oct 19, 2023
@JanMarvin JanMarvin mentioned this pull request Oct 20, 2023
10 tasks
@JanMarvin
Copy link
Owner Author

@lauraearle515 @Amaru6, maybe you guys can give this a try and see if it works for your use case.

You can install from this branch with the following command and example code is above

remotes::install_github("JanMarvin/openxlsx2#822")

I won't work on adding slicers to existing pivot tables (aka those that are loaded from a workbook) and wont work on further complicated cases. For the moment the slicer must be on the table of the pivot table.

@Amaru6
Copy link

Amaru6 commented Oct 21, 2023

Hi @JanMarvin . Thank you so much for your effort and time. Your example worked perfectly in my machine:

`

sessionInfo()
R version 4.2.2 (2022-10-31 ucrt)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19045)

Matrix products: default

locale:
[1] LC_COLLATE=Spanish_Peru.utf8 LC_CTYPE=Spanish_Peru.utf8
[3] LC_MONETARY=Spanish_Peru.utf8 LC_NUMERIC=C
[5] LC_TIME=Spanish_Peru.utf8

`
However, when I try to recreate my use case it doesn't work. Here is a fake data similar to the one I work with:

tribble(
  ~Total, ~char_1, ~año, ~mes, ~char_2, ~char_3,
  1.21, "a", 2023, "Mar", "fuente_1", "no",
  5, "b", 2023, "Ene", "fuente_1", "si",
  0.24, "c", 2021, "May", "fuente_2", "no",
  6.3, "d", 2022, "Jun", "fuente_1", "no",
  0.3, "e", 2022, "Jul", "fuente_2", "no",
  3504, "f", 2021, "Abr", "fuente_2", "no",
  88.4, "g", 2023, "Jun", "fuente_1", "no",
  0, "h", 2023, "Set", "fuente_1", "no",
  0, "i", 2023, "Jul", "fuente_1", "no",
  29.4, "j", 2021, "Jun", "fuente_2", "si"
) -> tbl_test
tbl_test
wb_test <- wb_workbook() |> 
  wb_add_worksheet(sheet = "Resumen") |> 
  wb_add_worksheet(sheet = "Detalle") |> 
  wb_add_data(sheet = "Detalle",
              x = tbl_test)
wb_test
data_to_pivot <- wb_data(wb_test, sheet = "Detalle")
data_to_pivot
vars_to_slicers <- c("char_2", "char_3")
wb_test$add_pivot_table(
  x = data_to_pivot,
  sheet = "Resumen",
  dims = "B10",
  rows = "char_1",
  cols = c("año", "mes"),
  data = "Total",
  slicer = vars_to_slicers,
  params = list(
    name = "pivot_1"
  )
)$add_slicer(
  x = data_to_pivot,
  sheet = "Resumen",
  varname = "char_2",
  pivot_table = "pivot_1"
)$add_slicer(
  x = data_to_pivot,
  sheet = "Resumen",
  varname = "char_3",
  pivot_table = "pivot_1"
)

This results in:
Error in .subset2(x, i, exact = exact) : attempt to select less than one element in get1index

When I only add the parameter name = "pivot_1", and not the slicers I get the following when I open the Excel file:
"Excel was unable to update the pivot table named "pivot_1" in the worksheet named "Resumen" because it would have overlaid another pivot table"

@JanMarvin
Copy link
Owner Author

Thank you for testing @Amaru6 ! (The error was caused by a simple typo, caused by late night coding ...).

I'm not yet sure how the default interface should look like. Unfortunately slicers use distinct column items similar to pivot tables, that's why I have to pass the wb_data() object to both functions. And slicers also require, that the pivot table has something like "unfolded" column information. That's why we have to pass slicer as a variable to wb_add_pivot_table() and cannot simply treat both functions independently.

And there is another little thing, we simply overwrite the extension list of the worksheet where we add the slicer. This needs some kind of integration.

Otherwise, it needs testing. I cannot test every corner case, therefore I'm glad if people help me out and report their findings. Even "everything works perfect" is a very useful reply in that regard.

This should work now:

library(openxlsx2)
tbl_test <- tibble::tribble(
  ~Total, ~char_1, ~año, ~mes, ~char_2, ~char_3,
  1.21, "a", 2023, "Mar", "fuente_1", "no",
  5, "b", 2023, "Ene", "fuente_1", "si",
  0.24, "c", 2021, "May", "fuente_2", "no",
  6.3, "d", 2022, "Jun", "fuente_1", "no",
  0.3, "e", 2022, "Jul", "fuente_2", "no",
  3504, "f", 2021, "Abr", "fuente_2", "no",
  88.4, "g", 2023, "Jun", "fuente_1", "no",
  0, "h", 2023, "Set", "fuente_1", "no",
  0, "i", 2023, "Jul", "fuente_1", "no",
  29.4, "j", 2021, "Jun", "fuente_2", "si"
)
# tbl_test

wb_test <- wb_workbook() |> 
  wb_add_worksheet(sheet = "Resumen") |> 
  wb_add_worksheet(sheet = "Detalle") |> 
  wb_add_data(sheet = "Detalle",
              x = tbl_test)
# wb_test

data_to_pivot <- wb_data(wb_test, sheet = "Detalle")
# data_to_pivot

vars_to_slicers <- c("char_2", "char_3")

wb_test$
  add_pivot_table(
    x = data_to_pivot,
    sheet = "Resumen",
    dims = "B10",
    rows = "char_1",
    cols = c("año", "mes"),
    data = "Total",
    slicer = vars_to_slicers,
    params = list(
      name = "pivot_1"
    )
  )$
  add_slicer(
    x = data_to_pivot,
    dims = "B2:D6",
    sheet = "Resumen",
    varname = "char_2",
    pivot_table = "pivot_1"
  )$
  add_slicer(
    x = data_to_pivot,
    dims = "F2:I6",
    sheet = "Resumen",
    varname = "char_3",
    pivot_table = "pivot_1"
  )

if (interactive()) wb_test$open()

@Amaru6
Copy link

Amaru6 commented Oct 21, 2023

Hi there. I ran the code after "This should work now" and it says:
Error in wb_test$add_pivot_table(x = data_to_pivot, sheet = "Resumen", : unused argument (varname = "char_2")

Does it has somethind to do with the fact that the arguments in add_pivot_table and add_slicer have changed?

I've tried the following (from reading your first example):

tribble(
  ~Total, ~char_1, ~año, ~mes, ~char_2, ~char_3,
  1.21, "a", 2023, "Mar", "fuente_1", "no",
  5, "b", 2023, "Ene", "fuente_1", "si",
  0.24, "c", 2021, "May", "fuente_2", "no",
  6.3, "d", 2022, "Jun", "fuente_1", "no",
  0.3, "e", 2022, "Jul", "fuente_2", "no",
  3504, "f", 2021, "Abr", "fuente_2", "no",
  88.4, "g", 2023, "Jun", "fuente_1", "no",
  0, "h", 2023, "Set", "fuente_1", "no",
  0, "i", 2023, "Jul", "fuente_1", "no",
  29.4, "j", 2021, "Jun", "fuente_2", "si"
) -> tbl_test
tbl_test
wb_test <- wb_workbook() |> 
  wb_add_worksheet(sheet = "Resumen") |> 
  wb_add_worksheet(sheet = "Detalle") |> 
  wb_add_data(sheet = "Detalle",
              x = tbl_test)
data_to_pivot <- wb_data(wb_test,sheet = "Detalle")
data_to_pivot
vars_to_slicer <- c("char_2", "char_3")
vars_to_slicer
wb_test$add_pivot_table(
  x = data_to_pivot,
  sheet = "Resumen",
  dims = "B10",
  rows = "char_1",
  cols = c("año", "mes"),
  data = "Total",
  pivot_table = "pivot_1", # CHANGE HERE
  slicer = vars_to_slicer
)$add_slicer(
  x = data_to_pivot,
  dims = "B2:D6",
  slicer = "char_2", # CHANGE HERE (no more varname)
  sheet = "Resumen",
  pivot_table = "pivot_1" 
)$add_slicer(
  x = data_to_pivot,
  dims = "F2:I6",
  sheet = "Resumen",
  slicer = "char_3", # CHANGE HERE (no more varname)
  pivot_table = "pivot_1"
)

This returns Error: xml import unsuccessful

@JanMarvin
Copy link
Owner Author

😵‍💫, typo. Your example should work now.

@JanMarvin
Copy link
Owner Author

Does it has somethind to do with the fact that the arguments in add_pivot_table and add_slicer have changed?

Yes, sorry, I've updated the API afterwards and forgot to update the code above. But now your code works and you can even play around a bit with various slicer options. Like descing sort order or multiple columns etc.

@Amaru6
Copy link

Amaru6 commented Oct 21, 2023

Now, this is awesome. It can replace small projects that require basic user interface (Shiny). Awesome public good! 👏
Everything works perfect.

@JanMarvin
Copy link
Owner Author

🎉 But please do some more tests with different files, different column types etc.!

And please test not only that the files open with Excel without warning, but create the pivot table and slicers from Excel and from openxlsx2 and compare them.

* `pivot_table` is always the name of the pivot table
* `slicer` is always a name of a slicer variable
…e cell is provided, create a cell range. use editAs = "oneCell". Similar to what redmonds spreadsheet software uses.
@JanMarvin JanMarvin merged commit 6712658 into main Oct 22, 2023
9 checks passed
@JanMarvin JanMarvin deleted the add_slicers branch October 22, 2023 13:27
@Amaru6
Copy link

Amaru6 commented Nov 8, 2023

Hi there, @JanMarvin

I noticed something while using the slicers

iris_2 <- iris |> as_tibble() |> 
  rename("Petal Length" = "Petal.Length") # "Split" the column name (Common for presentation purposes)
iris_2
wb_1 <- wb_workbook() |> 
  wb_add_worksheet(sheet = "x") |> 
  wb_add_data(x = iris_2,
              sheet = current_sheet()) |> 
  wb_add_worksheet(sheet = "y")
tbl_to_pivot <- wb_1 |> wb_data("x")
wb_1 |> 
  wb_add_pivot_table(
    x = tbl_to_pivot,
    sheet = "y",
    rows = "Species",
    data = "Petal.Width",
    pivot_table = "pivot_1",
    slicer = "Petal Length"
  ) |> 
  wb_add_slicer(
    x = tbl_to_pivot,
    pivot_table = "pivot_1",
    slicer = "Petal Length"
  )

Excel returns the following error:

Records removed: /xl/slicerCaches/slicerCache1.xml
Records removed: Segmentación de datos de /xl/slicers/slicer1.xml parte

In the mean time, I've been using the caption argument and my variable without spaces

@JanMarvin
Copy link
Owner Author

Thanks for the report, I've added a fix in #842

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement 😀 New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants