JanMarvin / openxlsx2

openxlsx2 - read, write and modify xlsx files
https://janmarvin.github.io/openxlsx2/
Other
119 stars 9 forks source link

unify function parameters #38

Closed JanMarvin closed 1 year ago

JanMarvin commented 2 years ago

currently there are a few varying options accross the functions. The worst are the counter intuitive ones in cloneWorksheet

JanMarvin commented 1 year ago
lhs rhs x ... origin df date1904 diagonalDown diagonalUp outline bottom bottom_color diagonal diagonal_color end horizontal left left_color right right_color start top top_color vertical borderId fillId fontId numFmtId pivotButton quotePrefix xfId indent justifyLastLine readingOrder relativeIndent shrinkToFit textRotation wrapText extLst hidden locked text author style visible width height font_name font_size font_color numFmt border border_color border_style bgFill text_bold text_strike text_italic text_underline gradientFill patternType bgColor fgColor b charset color condense extend family i name scheme shadow strike sz u vertAlign sheet row col file formatCode dims sqref type negative displayEmptyCellsAs markers high low first last colorSeries colorNegative colorAxis colorMarkers colorFirst colorLast colorHigh colorLow
%>% x x
as_xml x x
col2int x
convert_date x x x
convert_datetime x x x
convertToExcelDate x x
create_border x x x x x x x x x x x x x x x x x x
create_cell_style x x x x x x x x x x x x x x x x x x x
create_comment x x x x x x
create_dxfs_style x x x x x x x x x x x x x
create_fill x x x x x
create_font x x x x x x x x x x x x x x x x
create_hyperlink x x x x x
create_numfmt x x
create_sparklines x x x x x x x x x x x x x x x x x x x
current_sheet
dataframe_to_dims x
delete_data x
dims_to_dataframe x
get_cell_refs
get_date_origin x
get_named_regions x
guess_col_type
int2col x
na_strings
next_sheet
read_sheet_names x
read_xlsx x x
read_xml
remove_comment x x x
styles_on_sheet x
temp_xlsx x
wb_add_border x x x x x x x
wb_add_cell_style x x x x x x x x x x x x x x x x x x x x x
wb_add_chart_xml x x
wb_add_chartsheet x x x
wb_add_comment x x x x
wb_add_conditional_formatting x x x
wb_add_creators
wb_add_data x x x x
wb_add_data_table x x x
wb_add_data_validation x x
wb_add_fill x x x x
wb_add_filter x
wb_add_font x x x x x x x x x x x x x x
wb_add_form_control x x x x
wb_add_formula x x x
wb_add_image x x x x
wb_add_mschart x x
wb_add_named_region x x x
wb_add_numfmt x x
wb_add_page_break x x x
wb_add_pivot_table x x x
wb_add_plot x x x
wb_add_sparklines x
wb_add_style x
wb_add_worksheet x x x
wb_clean_sheet x
wb_clone_sheet_style
wb_clone_worksheet
wb_color x
wb_colour x
wb_copy_cells x x
wb_data x x x
wb_freeze_pane x
wb_get_active_sheet
wb_get_base_font
wb_get_cell_style x x
wb_get_creators
wb_get_named_regions x
wb_get_order
wb_get_selected
wb_get_sheet_name
wb_get_sheet_names
wb_get_sheet_visibility
wb_get_tables x
wb_get_worksheet x
wb_grid_lines x
wb_group_cols x
wb_group_rows x
wb_load x x
wb_merge_cells x
wb_open
wb_page_setup x x x x x
wb_protect x
wb_protect_worksheet x
wb_read x x
wb_remove_col_widths x
wb_remove_comment x x x x
wb_remove_creators
wb_remove_filter x
wb_remove_named_region x x
wb_remove_row_heights x
wb_remove_tables x
wb_remove_worksheet x
wb_save
wb_set_active_sheet x
wb_set_base_font x
wb_set_cell_style x x x
wb_set_col_widths x x
wb_set_creators
wb_set_header_footer x
wb_set_last_modified_by
wb_set_order
wb_set_row_heights x x
wb_set_selected x
wb_set_sheet_names
wb_set_sheet_visibility x
wb_sheet_data
wb_to_df x x
wb_ungroup_cols x
wb_ungroup_rows x
wb_unmerge_cells x
wb_workbook
wb_ws x
write_comment x x x
write_data x x x x
write_datatable x x x
write_file
write_formula x x x
write_xlsx x x x
xl_open x
xml_add_child x
xml_attr x
xml_attr_mod
xml_node x
xml_node_create
xml_node_name x
xml_rm_child x
xml_value x
JanMarvin commented 1 year ago
wb cols rows fill cellCoords xlsxFile tt startRow startCol rowNames colNames skipEmptyRows skipEmptyCols detectDates namedRegion na.strings na.numbers check.names sep.names fillMergedCells xml pointer escapes declaration whitespace empty_tags skip_control gridExpand macros bottom_border left_border right_border top_border inner_hgrid inner_hcolor inner_vgrid inner_vcolor applyAlignment applyBorder applyFill applyFont applyNumberFormat applyProtection tabColor zoom comment rule params creators array withFilter sep applyCellStyle removeCellStyle inline_strings tableStyle tableName firstColumn lastColumn bandedRows bandedCols operator value allowBlank showInputMsg showErrorMsg errorStyle errorTitle error promptTitle prompt pattern gradient_fill every_nth_col every_nth_row size bold italic underline link range checked rowOffset colOffset units dpi graph localSheet overwrite customMenu description is_function functionGroupId help localName publishToServer statusBar vbProcedure workbookParameter numfmt
%>%
as_xml
col2int
convert_date
convert_datetime
convertToExcelDate
create_border
create_cell_style
create_comment
create_dxfs_style
create_fill
create_font
create_hyperlink
create_numfmt
create_sparklines
current_sheet
dataframe_to_dims
delete_data x x x
dims_to_dataframe x
get_cell_refs x
get_date_origin x
get_named_regions
guess_col_type x
int2col
na_strings
next_sheet
read_sheet_names
read_xlsx x x x x x x x x x x x x x x x x
read_xml x x x x x x x
remove_comment x x
styles_on_sheet x
temp_xlsx x
wb_add_border x x x x x x x x x
wb_add_cell_style x x x x x x x
wb_add_chart_xml x x
wb_add_chartsheet x x x
wb_add_comment x x
wb_add_conditional_formatting x x x x x
wb_add_creators x x
wb_add_data x x x x x x x x x x x x
wb_add_data_table x x x x x x x x x x x x x x x x x
wb_add_data_validation x x x x x x x x x x x x x
wb_add_fill x x x x x
wb_add_filter x x x
wb_add_font x x x x x
wb_add_form_control x x x x
wb_add_formula x x x x x x
wb_add_image x x x x x x x
wb_add_mschart x x
wb_add_named_region x x x x x x x x x x x x x x x x x
wb_add_numfmt x x
wb_add_page_break x
wb_add_pivot_table x x x x
wb_add_plot x x x x x x x
wb_add_sparklines x
wb_add_style x
wb_add_worksheet x x x
wb_clean_sheet x
wb_clone_sheet_style x
wb_clone_worksheet x
wb_color
wb_colour
wb_copy_cells x
wb_data x
wb_freeze_pane x
wb_get_active_sheet x
wb_get_base_font x
wb_get_cell_style x
wb_get_creators x
wb_get_named_regions
wb_get_order x
wb_get_selected x
wb_get_sheet_name x
wb_get_sheet_names x
wb_get_sheet_visibility x
wb_get_tables x
wb_get_worksheet x
wb_grid_lines x
wb_group_cols x x
wb_group_rows x x
wb_load x
wb_merge_cells x x x
wb_open x
wb_page_setup x
wb_protect x
wb_protect_worksheet x
wb_read x x x x x x x x x x x x x
wb_remove_col_widths x x
wb_remove_comment x x
wb_remove_creators x x
wb_remove_filter x
wb_remove_named_region x
wb_remove_row_heights x x
wb_remove_tables x
wb_remove_worksheet x
wb_save x x
wb_set_active_sheet x
wb_set_base_font x
wb_set_cell_style x
wb_set_col_widths x x
wb_set_creators x x
wb_set_header_footer x
wb_set_last_modified_by x
wb_set_order x
wb_set_row_heights x x
wb_set_selected x
wb_set_sheet_names x
wb_set_sheet_visibility x x
wb_sheet_data
wb_to_df x x x x x x x x x x x x x
wb_ungroup_cols x x
wb_ungroup_rows x x
wb_unmerge_cells x x x
wb_workbook
wb_ws x
write_comment x x
write_data x x x x x x x x x x x x
write_datatable x x x x x x x x x x x x x x x x x
write_file x
write_formula x x x x x x
write_xlsx
xl_open
xml_add_child x
xml_attr x
xml_attr_mod x x
xml_node x
xml_node_create x x
xml_node_name x
xml_rm_child x
xml_value x
JanMarvin commented 1 year ago
filter data fun xy fileType sparklines style_name gridLines rowColHeaders header footer oddHeader oddFooter evenHeader evenFooter firstHeader firstFooter hasDrawing paperSize orientation hdpi vdpi numbers characters styles merged_cells from to old new auto indexed hex theme tint as_value as_ref transpose firstActiveRow firstActiveCol firstRow firstCol index show print collapsed levels data_only calc_chain scale fitToWidth fitToHeight printTitleRows printTitleCols summaryRow summaryCol protect password lockStructure lockWindows fileSharing username readOnlyRecommended properties table path fontSize fontColor fontName widths LastModifiedBy sheets heights showFormula convert types named_region creator title subject category datetimeCreated head body tail fl asTable interactive xml_node xml_child level level1 level2 level3 xml_content xml_attributes xml_name xml_children which
%>%
as_xml
col2int
convert_date
convert_datetime
convertToExcelDate
create_border
create_cell_style
create_comment
create_dxfs_style
create_fill
create_font
create_hyperlink
create_numfmt
create_sparklines
current_sheet
dataframe_to_dims
delete_data
dims_to_dataframe
get_cell_refs
get_date_origin
get_named_regions
guess_col_type
int2col
na_strings
next_sheet
read_sheet_names
read_xlsx
read_xml
remove_comment
styles_on_sheet
temp_xlsx
wb_add_border
wb_add_cell_style
wb_add_chart_xml
wb_add_chartsheet
wb_add_comment
wb_add_conditional_formatting
wb_add_creators
wb_add_data
wb_add_data_table
wb_add_data_validation
wb_add_fill
wb_add_filter
wb_add_font
wb_add_form_control
wb_add_formula
wb_add_image
wb_add_mschart
wb_add_named_region
wb_add_numfmt
wb_add_page_break
wb_add_pivot_table x x x
wb_add_plot x x
wb_add_sparklines x
wb_add_style x
wb_add_worksheet x x x x x x x x x x x x x x x
wb_clean_sheet x x x x
wb_clone_sheet_style x x
wb_clone_worksheet x x
wb_color x x x x x
wb_colour x x x x x
wb_copy_cells x x x x
wb_data
wb_freeze_pane x x x x
wb_get_active_sheet
wb_get_base_font
wb_get_cell_style
wb_get_creators
wb_get_named_regions
wb_get_order
wb_get_selected
wb_get_sheet_name x
wb_get_sheet_names
wb_get_sheet_visibility
wb_get_tables
wb_get_worksheet
wb_grid_lines x x
wb_group_cols x x
wb_group_rows x x
wb_load x x
wb_merge_cells
wb_open
wb_page_setup x x x x x x x x x x x
wb_protect x x x x x x x
wb_protect_worksheet x x x
wb_read
wb_remove_col_widths
wb_remove_comment
wb_remove_creators
wb_remove_filter
wb_remove_named_region
wb_remove_row_heights
wb_remove_tables x
wb_remove_worksheet
wb_save x
wb_set_active_sheet
wb_set_base_font x x x
wb_set_cell_style
wb_set_col_widths x
wb_set_creators
wb_set_header_footer x x x x x x
wb_set_last_modified_by x
wb_set_order x
wb_set_row_heights x
wb_set_selected
wb_set_sheet_names x x
wb_set_sheet_visibility
wb_sheet_data
wb_to_df x x x x
wb_ungroup_cols
wb_ungroup_rows
wb_unmerge_cells
wb_workbook x x x x x
wb_ws
write_comment x
write_data
write_datatable
write_file x x x x
write_formula
write_xlsx x
xl_open x
xml_add_child x x x
xml_attr x x x
xml_attr_mod x x
xml_node x x x
xml_node_create x x x
xml_node_name x x
xml_rm_child x x x x
xml_value x x x
JanMarvin commented 1 year ago

Should break this into groups, maybe identical to the one one pagedown reference site. It is expected for a set of groups to share some arguments (e.g. the xml functions share arguments no other function needs).

library(openxlsx2)
funs <- ls("package:openxlsx2")
funs <- funs[!funs %in% c("style_mgr", "wbChartSheet", "wbComment", "wbHyperlink", "wbSheetData", "wbWorkbook", "wbWorksheet")]

arguments <- sapply(funs, function(x) names(formals(x)))
uniargs   <- unique(unlist(arguments))

argmat <- as.data.frame(
  matrix("", nrow = length(arguments), ncol = length(uniargs))
)

colnames(argmat) <- uniargs
rownames(argmat) <- names(arguments)

for (row in seq_along(arguments)) {
  argmat[row, arguments[[row]]] <- "x"
}
olivroy commented 1 year ago

Hello, I don't know if it is related, but I think that argument names should stick to one convention: either snake_case or camelCase..

It will be hard for the package to take its place if it's hard to remember if arguments are snake case or not.

JanMarvin commented 1 year ago

Hi @olivroy , of course it is related, but as you can see, the initial issue is now one and half year old. Since then not a lot of time was spent on the issue. I'm planning to do a 1.0 release soon -- maybe the next release or the one after the next release -- which shall provide a stable API So any work regarding the API has to be introduced in the upcoming weeks. The tricky part is providing a backward compatible solution, one that does not break all existing code.

But I'm not worried about its place in history. I assume that this package provides a unique solution to a variety of issues and it fulfills mine just fine, probably that's why I haven't already worked on this. But if you want to work on this, please reach out, maybe begin with a small pull request and I'm pretty sure that we can work something out.

olivroy commented 1 year ago

Yes. I agree. It is very interesting

I may look into it! The lifecycle tidyverse package may help with this https://lifecycle.r-lib.org/articles/communicate.html#renaming-an-argument

I assume you'd rather have arguments be camelCase and all functions to snake_case?

Edit:

functions rename
convertToExcelDate -> convert_to_excel_date
optional:
create_tablestyle -> create_table_style
_numfmt -> _num_fmt (since using numFmt in some places)
# maybe issues with the documentation here since R6 class are camelCase (maybe wb_sheet_data could have @keywords internal 
wb_sheet_data 

Parameters xlsxFile could be deprecated to encourage users strongly to use file and file could be use throughout named_region seems to be used consistently, however, it is not consistent with the rest of the API. maybe could be namedRegion.

JanMarvin commented 1 year ago

I do not really see the lifecycle package required, the same effect can be created using .Deprecated() (and I don't want to introduce tidyverse dependencies). Every generation of software developers has reasons for their fashion of code style. In R nowadays everyone seems to follow the tidyverse snake case style and Jordan and I were switching functions to it a while ago. In the open xml standard though, everything is camel case. So even though the input might be creat_fill(gradient_fill = "...") the output must be <gradientFill attr="..."/>. This makes modifications a bit harder, because one cannot simply apply "replace all".

Renaming functions is simpler than renaming arguments especially if one wants to avoid creating dozens of identical arguments.

olivroy commented 1 year ago

I agree that renaming functions is easier. But what do you think about renaming arguments to camelCase like font_name -> font, font_size -> fontSize etc.

I could check this out in the coming weeks if you think it's useful!

JanMarvin commented 1 year ago

I'm not sure if this would be really helpful or if it would create more confusion to the user when camel case and snake case are mixed together. My approach would be to switch arguments to snake case too, hoping that most of the current functions are already snake case, but maybe provide a standardization(...) function for a ... argument that can convert camel case to snake case under the hood.

Something like this (we use a similar approach with color and colour)

x <- "camelCase"
# adaption of https://stackoverflow.com/a/43768828/12340029
gsub(
  pattern = "(\\G(?!^)|\\b[a-zA-Z][a-z]*)([A-Z][a-z]*|\\d+)",
  replacement = "\\L\\1_\\2",
  x = x, perl = TRUE
)
#> [1] "camel_case"
olivroy commented 1 year ago

Ah ok!

Well, it seems like a harder task to convert arguments to snake_case... from what I can see currently, most arguments are camel case. and most functions are snake case

The only functions that have exclusively snake_case arguments seem to be wb_load(), wb_add_border() , create_dxfs_style().

But most have camelCase arguments. read_xlsx(), write_xlsx(), wb_workbook(), wb_add_data() etc. but that is possibly inherited from openxlsx.

For reference, in ggplot2, all the functions are camel_case, but arguments are separated by dots. i.e. show.legend, inherits.aes etc. https://github.com/tidyverse/ggplot2/issues/5751

JanMarvin commented 1 year ago

Thanks for the hint. I cannot say that I've given it to much thought lately, but if things are charged I would want to provide a consistent API and breakage should be minimal. Like under the hood changes and soft deprecating.

But I fully agree that it's not a trivial change and one that requires some thought. Hence, the unreadable table above. And unfortunately while everyone loves a nice API and a well written documentation, there were always other more interesting things to do.

JanMarvin commented 1 year ago

I want to change the order where required so that dims is always the third in wb wrapper functions: wb, sheet, and dims.

JanMarvin commented 1 year ago

Thanks for the hint. I cannot say that I've given it to much thought lately, but if things are charged I would want to provide a consistent API and breakage should be minimal. Like under the hood changes and soft deprecating.

But I fully agree that it's not a trivial change and one that requires some thought. Hence, the unreadable table above. And unfortunately while everyone loves a nice API and a well written documentation, there were always other more interesting things to do.

@jmbarbone and @sjewo , do you guys have any recommendations how to move on? Snake case functions and camel case arguments or ...?

My biggest wish is to avoid hard deprecations (if this is a word), especially since I've already written a couple of hundred lines of openxlsx2 code in production and do not want to rewrite everything and assume that the same is true for the users. Otherwise I do not really have a strong opinion on either.

JanMarvin commented 1 year ago

Came across readxl which uses snake case for arguments.

jmbarbone commented 1 year ago

For me, snake_case has become a de-facto style for function names and parameters (and {R6} fields and methods) in R, which makes it more sensible and more preferred. Even though the xml back-end may use camelCase, it's pretty trivial to convert snake_case to camelCase, and I'd expect an R interface to feel more like R than anything else.

I think for a 1.0 release, unifying the naming conventions sounds appropriate. The {openxlsx} functions mostly used camelCase for names parameters, but not entirely. For {openxlsx2}, nearly all functions use snake_case (except for convertToExcelDate()) but more parameters use camelCase. It would be a hefty task, but maybe a release prior to 1.0 could introduce deprecation warnings, then 1.0 would entirely remove them.

JanMarvin commented 1 year ago

Appreciate the reply @jmbarbone . And as written before, I agree that if anything, switching to snake_case should be preferred. But I would want to avoid throwing around deprecation warnings on short notice. In a pre-1.0 release and deprecate in 1.0. Realistically, if we continue on a monthly release cycle, much of the current code using openxlsx2 will need to be rewritten by users, including two CRAN dependencies. And even though we indicate in our README that this might happen, I would prefer to avoid it.

As an alternative, I suggest something like #678. While I know you weren't a fan of the under-the-hood changing, and probably still are, at least they guarantee that the old code still runs. The modified wb_to_df() function is probably one of our longest, but as one might expect, there are a lot of changes around the codebase and it will be very hard to track code changes. And I will not sacrifice a working codebase for a purely cosmetic change.

olivroy commented 1 year ago

I think it is a very good idea to switch to snake_case. (I originally pushed for camelCase args, just because it seemed like the easiest, least effort)

As I wanted to respect the existing code base, I didn't want to push it too much, but like @jmbarbone said, snake_case is also the default for me. It's just easier this way

I will take a look in the coming weeks, and see if / when I can contribute.

sjewo commented 1 year ago

I also think that a consistent use of spelling for arguments makes sense. I can't judge whether snake_case is more widely used than camelCase.

Either way, if you want to change arguments without breaking user code, something like this procedure might be an option:

# table of translations between old and new arguments
translate_table <- data.frame(old = c("xA", "xB"),
                              new = c("x_A", "x_B"))

# The core function with programm logic
core_function <- function(x_A, x_B) {
  message("x_A:", x_A, "\nx_B:", x_B)
}

# A public function for user interaction
public_function <- function(...) {

  # get all arguments
  arg.list <- list(...)

  # replace old arguments with new arguments
  names(arg.list) <- sapply(names(arg.list), function(x) {
    if(x %in% translate_table$old) {
      message("Please use '", translate_table$new[translate_table$old == x], "' instead of '", x, "'.")
      return(translate_table$new[translate_table$old == x])
    } else {
    return(x)
    }
  })

  # Check if user defines a argument with old and new name
  if(any(duplicated(arg.list))) {
    multi.args <- names(arg.list)[duplicated(arg.list)]
    warn <- sapply(multi.args, function(x) 
    paste("The argument '", x, "'is defined more than once.\nPlease use only '", translate_table$new[translate_table$new==x], "'. The spelling '", translate_table$old[translate_table$new==x], "' is deprecated."))
    stop(warn)
  }

  # call the core function with new arguments
  return(do.call(core_function, arg.list))
}
> public_function(xA = 1, xB = 2)
Please use 'x_A' instead of 'xA'.
Please use 'x_B' instead of 'xB'.
x_A:1
x_B:2
> public_function(x_A = 1, x_B = 2)
x_A:1
x_B:2
> public_function(x_A = 1, xB = 2)
Please use 'x_B' instead of 'xB'.
x_A:1
x_B:2
JanMarvin commented 1 year ago

Thanks @sjewo , at least in the tidyverse, googles style guide wants functions as CamelCase (with an upper first letter) and a (.CamelCase for internal functions). R core still uses whatever, so ... Your approach is somewhat similar to my own. The only issue with ... is something like #598 , but we have to die one death, so that's acceptable to me.

JanMarvin commented 1 year ago

I made a list of all the functions and arguments that are camelCase and should be converted to snake_case in #679 . And because that was such a boring task, I almost wanted to drop it, 20 functions in.

Looking at this list, that's just too many changes all around, a gentle deprecation or dropping is off the table for me. Most of these functions are wrapper functions, so we have double the number of replacements in the R6 wb objects. This is a task comparable to counting sheep for me.

jmbarbone commented 1 year ago

To be less intrusive, the snake_case variants could silently replace camelCase for one version, then later use of the old parameters could throw .Deprecated warnings. This would be a little softer and prevent a ton of warnings before notice:

foo <- function(param_one = paramOne, param_two = paramTwo, ..., paramOne, paramTwo) {
  force(param_one)
  force(param_two)
  list(param_one, param_two)
}

identical(
  foo(paramOne = 1, paramTwo = 2),
  foo(param_one = 1, param_two = 2)
)
#> [1] TRUE

cc_deprecate <- function(x, snake = NULL) {
  camel <- deparse1(substitute(x))
  if (!missing(x)) {
    # convert cc camelCase to snake_case
    if (is.null(snake)) {
      snake <- gsub("([a-z])([A-Z])", "\\1_\\2", camel)
      snake <- tolower(snake)
    }

    # get function that uses cc_deprecate
    fun <- as.character(sys.call(-1))[1]
    .Deprecated(msg = sprintf(
      "Use '%s(%s)' instead of '%s(%s)'",
      fun,
      snake,
      fun,
      camel
    ))
  }
  invisible()
}

foo <- function(param_one = paramOne, param_two = paramTwo, ..., paramOne, paramTwo) {
  force(param_one)
  force(param_two)
  cc_deprecate(paramOne)
  cc_deprecate(paramTwo)
  list(param_one, param_two)
}

foo(paramOne = 1, paramTwo = 2)
#> Warning: Use 'foo(param_one)' instead of 'foo(paramOne)'
#> Warning: Use 'foo(param_two)' instead of 'foo(paramTwo)'
#> [[1]]
#> [1] 1
#> 
#> [[2]]
#> [1] 2
foo(param_one = 1, param_two = 2)
#> [[1]]
#> [1] 1
#> 
#> [[2]]
#> [1] 2

Created on 2023-07-09 with reprex v2.0.2

JanMarvin commented 1 year ago

It is a smart approach and I like the deparse1(substitute(x)) and I think about the same. Now silently convert. Publish a 1.0 with this. With 2.0 deprecate the old camelCase arguments with a warning and with 3.0 drop the camelCase arguments. But for me, the next big API releases are 1 and 2 years in the future, not 1 and 2 months in the future.

I'm going with .... in #678 because otherwise we would have to start with the following, right?

#' @param paramOne,param_one foo
#' @param paramTwo,param_two foo
#' @export
foo <- function(paramOne, param_one, paramTwo, param_two) {
   ...
}

My approach is this

#' @param param_one foo
#' @export
foo <- function(param_one = next_sheet(), ...) {
  standardize(...) # convert everything in ... to snake_case including overrides
   ...
}
# should still work
foo(paramOne = next_sheet()))

The only real issue I see with my approach is that ... accepts all kind of input and I have to come up with a way to let the user know about unused arguments.

JanMarvin commented 1 year ago

This is and will remain an ongoing task for the foreseeable future, but the issue is now outdated