Skip to content

Feature: introduce xl_cell_general class (value, formula, hyperlink)#101

Open
billdenney wants to merge 15 commits into
masterfrom
xl-cell-general
Open

Feature: introduce xl_cell_general class (value, formula, hyperlink)#101
billdenney wants to merge 15 commits into
masterfrom
xl-cell-general

Conversation

@billdenney

@billdenney billdenney commented Apr 7, 2026

Copy link
Copy Markdown
Collaborator
  • New xl_cell_general() constructor: vector-like list of per-cell records supporting value, formula, and hyperlink fields with full recycling in data frames (length(), [, c(), rep(), as.data.frame(), print() S3 methods)
  • xl_formula() and xl_hyperlink() now return xl_cell_general objects (backward-compatible: same call syntax, same write_xlsx() output)
  • xl_hyperlink() uses worksheet_write_url_opt() for proper URL hyperlinks with optional display text and tooltip via named list hyperlink spec
  • Formula cells support pre-calculated values via worksheet_write_formula_num() / worksheet_write_formula_str() for static xlsx exports
  • C: add COL_CELL_GENERAL enum value, list_get() helper, write_cell_general()
  • 95 new tests with full coverage of constructor, S3 methods, and write_xlsx
  • New vignette: "Writing Special Cell Types with writexl"
  • Update WORDLIST for new documentation terms

Fix #96
Fix #5
Fix #89 (via updated dubquote function)

billdenney and others added 12 commits April 7, 2026 01:40
- New xl_cell_general() constructor: vector-like list of per-cell records
  supporting value, formula, and hyperlink fields with full recycling in
  data frames (length(), [, c(), rep(), as.data.frame(), print() S3 methods)
- xl_formula() and xl_hyperlink() now return xl_cell_general objects
  (backward-compatible: same call syntax, same write_xlsx() output)
- xl_hyperlink() uses worksheet_write_url_opt() for proper URL hyperlinks
  with optional display text and tooltip via named list hyperlink spec
- Formula cells support pre-calculated values via worksheet_write_formula_num()
  / worksheet_write_formula_str() for static xlsx exports
- C: add COL_CELL_GENERAL enum value, list_get() helper, write_cell_general()
- 95 new tests with full coverage of constructor, S3 methods, and write_xlsx
- New vignette: "Writing Special Cell Types with writexl"
- Update WORDLIST for new documentation terms

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The string field is removed from the hyperlink named list. A character
value alongside hyperlink now serves as the display text passed to
worksheet_write_url_opt(), so value, formula, and hyperlink can all be
set on the same cell without any precedence conflict. xl_hyperlink(name=)
is updated to store name as value rather than hyperlink$string.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove the duplicated switch/if-else chain in the value-only path of
write_cell_general(). Plain values are now dispatched through the
existing get_type() + write_cell() mechanism at index 0, eliminating
~50 lines of redundant code. Move write_cell() before write_cell_general()
in the file and add a forward declaration to resolve the mutual dependency.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Calling xl_cell_general() with no arguments now stops with an informative
message directing users to value = NA for an explicit empty cell. This
makes intent clear at the call site and prevents accidental use of the
default. The 1L floor in the n-calculation is removed since at least one
argument is now always present.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Creates a five-sheet xlsx file covering every package feature:
- Sheet 1 (basic_types): logical, integer, double (incl. Inf), character,
  Date, and POSIXct columns with NA in every type
- Sheet 2 (formulas): xl_formula() with and without NA
- Sheet 3 (hyperlinks): xl_hyperlink() plain and named, NA URLs
- Sheet 4 (cell_general): xl_cell_general() for every field combination —
  value-only (all scalar types), NA (explicit empty), formula-only,
  formula+numeric precalc, formula+string precalc, plain hyperlink,
  hyperlink+display text, hyperlink+tooltip
- Sheet 5 (mixed_types): mixed-type column built with c()

Also tests col_names=FALSE, format_headers=FALSE, round-trip spot-checks
via readxl, and lxw_version() return type. Each row carries an "expected"
column describing exactly what should appear in Excel for manual inspection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Use \$<- assignment for all xl_formula/xl_hyperlink/xl_cell_general
  columns so the intended column names ('result', 'plain_link',
  'named_link') appear in Excel rather than the hardcoded 'x' name
  from as.data.frame.xl_cell_general
- formulas sheet: formulas now reference col A (the x values): =A2*2, =A3*2
- cell_general sheet: formulas reference col B (the result column):
  =B2+1, =SUM(B2:B3), =TEXT(B2,"0")
- mixed_types sheet: formula changed to =B2*2 (references numeric value
  in B2; B3 is a string and cannot be used in arithmetic)
- Add column-name round-trip assertions for formulas and hyperlinks sheets

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The method is necessary for data.frame(col = xl_cell_general(...)) to
work without error. The previous version set names = 'x', causing
data.frame() to override the caller's argument name with 'x' (or 'x.1'
on collision). The fix: omit the names attribute entirely (names = NULL).

R's data.frame() skips the inner-name override when length(names(xi)) == 0,
leaving vnames[[i]] as the original argument name — the same mechanism
used by I(list(...)). With names = NULL, data.frame(website = xl_hyperlink(...))
now produces a column named 'website' as expected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…; remove dead COL_FORMULA/COL_HYPERLINK C paths

- xl_hyperlink() restored to =HYPERLINK() formula approach (readxl-compatible)
- xl_hyperlink_cell() added for native cell-level hyperlinks via worksheet_write_url_opt()
- dubquote() now doubles internal double-quote characters for correct Excel escaping
- COL_FORMULA and COL_HYPERLINK removed from C enum; write_cell_formula() and
  write_cell_hyperlink() removed — all package-specific classes route through COL_CELL_GENERAL
- Tests updated: xl_hyperlink() tests check formula field; xl_hyperlink_cell() tests added
- Integration test: hyperlinks sheet gains cell_link column demonstrating xl_hyperlink_cell()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…t DAG

Extract write_atomic_value() from write_cell() so that write_cell_general()
can dispatch plain values without calling back into write_cell().  The call
graph is now a strict DAG (no forward declaration needed):

  write_cell() -> write_cell_general() -> write_atomic_value() -> write_cell_*()
               -> write_atomic_value()

write_cell() itself becomes a simple two-branch if rather than a full switch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add xl_hyperlink_cell() to xl_formula.Rd; regenerate xl_cell_general.Rd.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…R field

The blank line and free-form text after COPYRIGHT HOLDER was not valid DCF,
causing an R CMD check NOTE. The third-party license note is preserved as a
continuation line of the COPYRIGHT HOLDER field.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@billdenney

Copy link
Copy Markdown
Collaborator Author

@jeroen, do you want to review this? I think it's complete at this point.

The only part that is not backward compatible is the fact that the formula and hyperlinks now both go through the new general writing path and are contained within the new S3 class. That also means that the old S3 classes are removed. I don't think that directly modifying the previous S3 classes was an intended supported method, so that seems like it would be okay to me. The only other thing may be a problem is if people have any tests (e.g. inherits()) or other behavior expecting those classes.

@billdenney billdenney mentioned this pull request Apr 8, 2026
billdenney and others added 2 commits April 8, 2026 18:04
… Copyright field

The LICENSE stub should only contain YEAR and COPYRIGHT HOLDER per the DCF
spec. The reference to inst/COPYRIGHT for bundled third-party code
(libxlsxwriter) now lives in a proper Copyright: field in DESCRIPTION,
which is the recommended location per Writing R Extensions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…t field

Files in inst/ are installed into the package root, so the installed path
is COPYRIGHT not inst/COPYRIGHT, matching the RcppEigen convention.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: New object type for containing all options for single cells Need to escape quotes prior to writing formula Support writing formulas

1 participant