fast_excel 0.5.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +5 -1
  3. data/.gitignore +3 -0
  4. data/.octocov.yml +28 -0
  5. data/CHANGELOG.md +9 -0
  6. data/Gemfile +4 -2
  7. data/Rakefile +4 -1
  8. data/examples/comment_options.rb +39 -0
  9. data/fast_excel.gemspec +3 -2
  10. data/lib/fast_excel/binding/workbook.rb +53 -6
  11. data/lib/fast_excel/binding/worksheet.rb +28 -4
  12. data/lib/fast_excel/binding.rb +116 -13
  13. data/lib/fast_excel.rb +13 -12
  14. data/libxlsxwriter/.cirrus.yml +9 -0
  15. data/libxlsxwriter/.github/workflows/cmake_actions.yml +10 -6
  16. data/libxlsxwriter/.github/workflows/code_style.yml +2 -0
  17. data/libxlsxwriter/.github/workflows/make_32_actions.yml +43 -0
  18. data/libxlsxwriter/.github/workflows/windows_build.yml +7 -6
  19. data/libxlsxwriter/.github/workflows/zig_build.yml +1 -3
  20. data/libxlsxwriter/.gitignore +9 -7
  21. data/libxlsxwriter/.indent.pro +6 -0
  22. data/libxlsxwriter/CMakeLists.txt +377 -238
  23. data/libxlsxwriter/Changes.txt +189 -0
  24. data/libxlsxwriter/LICENSE.txt +1 -1
  25. data/libxlsxwriter/Makefile +36 -4
  26. data/libxlsxwriter/Readme.md +1 -1
  27. data/libxlsxwriter/build.zig +181 -92
  28. data/libxlsxwriter/build.zig.zon +15 -4
  29. data/libxlsxwriter/cocoapods/libxlsxwriter-umbrella.h +4 -0
  30. data/libxlsxwriter/include/xlsxwriter/app.h +2 -1
  31. data/libxlsxwriter/include/xlsxwriter/chart.h +134 -1
  32. data/libxlsxwriter/include/xlsxwriter/chartsheet.h +2 -1
  33. data/libxlsxwriter/include/xlsxwriter/comment.h +2 -1
  34. data/libxlsxwriter/include/xlsxwriter/common.h +12 -8
  35. data/libxlsxwriter/include/xlsxwriter/content_types.h +3 -1
  36. data/libxlsxwriter/include/xlsxwriter/core.h +2 -1
  37. data/libxlsxwriter/include/xlsxwriter/custom.h +2 -1
  38. data/libxlsxwriter/include/xlsxwriter/drawing.h +2 -1
  39. data/libxlsxwriter/include/xlsxwriter/format.h +34 -3
  40. data/libxlsxwriter/include/xlsxwriter/hash_table.h +2 -1
  41. data/libxlsxwriter/include/xlsxwriter/metadata.h +5 -1
  42. data/libxlsxwriter/include/xlsxwriter/packager.h +6 -1
  43. data/libxlsxwriter/include/xlsxwriter/relationships.h +3 -1
  44. data/libxlsxwriter/include/xlsxwriter/rich_value.h +51 -0
  45. data/libxlsxwriter/include/xlsxwriter/rich_value_rel.h +50 -0
  46. data/libxlsxwriter/include/xlsxwriter/rich_value_structure.h +53 -0
  47. data/libxlsxwriter/include/xlsxwriter/rich_value_types.h +49 -0
  48. data/libxlsxwriter/include/xlsxwriter/shared_strings.h +2 -1
  49. data/libxlsxwriter/include/xlsxwriter/styles.h +2 -1
  50. data/libxlsxwriter/include/xlsxwriter/table.h +2 -1
  51. data/libxlsxwriter/include/xlsxwriter/theme.h +2 -1
  52. data/libxlsxwriter/include/xlsxwriter/third_party/ioapi.h +4 -4
  53. data/libxlsxwriter/include/xlsxwriter/third_party/zip.h +3 -3
  54. data/libxlsxwriter/include/xlsxwriter/utility.h +58 -7
  55. data/libxlsxwriter/include/xlsxwriter/vml.h +2 -1
  56. data/libxlsxwriter/include/xlsxwriter/workbook.h +59 -2
  57. data/libxlsxwriter/include/xlsxwriter/worksheet.h +159 -13
  58. data/libxlsxwriter/include/xlsxwriter/xmlwriter.h +11 -10
  59. data/libxlsxwriter/include/xlsxwriter.h +5 -4
  60. data/libxlsxwriter/libxlsxwriter.podspec +6 -6
  61. data/libxlsxwriter/src/Makefile +2 -1
  62. data/libxlsxwriter/src/app.c +2 -1
  63. data/libxlsxwriter/src/chart.c +360 -63
  64. data/libxlsxwriter/src/chartsheet.c +2 -1
  65. data/libxlsxwriter/src/comment.c +2 -1
  66. data/libxlsxwriter/src/content_types.c +22 -1
  67. data/libxlsxwriter/src/core.c +2 -1
  68. data/libxlsxwriter/src/custom.c +2 -1
  69. data/libxlsxwriter/src/drawing.c +7 -3
  70. data/libxlsxwriter/src/format.c +21 -1
  71. data/libxlsxwriter/src/hash_table.c +2 -1
  72. data/libxlsxwriter/src/metadata.c +176 -20
  73. data/libxlsxwriter/src/packager.c +306 -6
  74. data/libxlsxwriter/src/relationships.c +25 -1
  75. data/libxlsxwriter/src/rich_value.c +191 -0
  76. data/libxlsxwriter/src/rich_value_rel.c +142 -0
  77. data/libxlsxwriter/src/rich_value_structure.c +162 -0
  78. data/libxlsxwriter/src/rich_value_types.c +199 -0
  79. data/libxlsxwriter/src/shared_strings.c +2 -1
  80. data/libxlsxwriter/src/styles.c +31 -7
  81. data/libxlsxwriter/src/table.c +2 -1
  82. data/libxlsxwriter/src/theme.c +2 -1
  83. data/libxlsxwriter/src/utility.c +136 -46
  84. data/libxlsxwriter/src/vml.c +2 -1
  85. data/libxlsxwriter/src/workbook.c +191 -10
  86. data/libxlsxwriter/src/worksheet.c +514 -34
  87. data/libxlsxwriter/src/xmlwriter.c +17 -22
  88. data/libxlsxwriter/third_party/minizip/Makefile.orig +1 -1
  89. data/libxlsxwriter/third_party/minizip/configure.ac +1 -1
  90. data/libxlsxwriter/third_party/minizip/ioapi.h +6 -6
  91. data/libxlsxwriter/third_party/minizip/miniunz.c +16 -2
  92. data/libxlsxwriter/third_party/minizip/unzip.c +4 -4
  93. data/libxlsxwriter/third_party/minizip/unzip.h +1 -1
  94. data/libxlsxwriter/third_party/minizip/zip.c +5 -5
  95. data/libxlsxwriter/third_party/minizip/zip.h +3 -3
  96. data/libxlsxwriter/version.txt +1 -1
  97. data/sonar-project.properties +4 -0
  98. data/test/color_to_hex_test.rb +15 -0
  99. data/test/comment_opt_test.rb +76 -0
  100. data/test/date_test.rb +14 -0
  101. data/test/format_test.rb +5 -1
  102. data/test/get_worksheet_test.rb +28 -0
  103. data/test/test_helper.rb +7 -4
  104. data/test/tmpdir_test.rb +32 -0
  105. data/test/validations_test.rb +25 -19
  106. data/test/worksheet_test.rb +10 -2
  107. metadata +42 -12
  108. data/libxlsxwriter/cmake/FindMINIZIP.cmake +0 -121
  109. data/libxlsxwriter/cmake/FindPackage.cmake +0 -183
  110. data/libxlsxwriter/cmake/i686-toolchain.cmake +0 -7
  111. data/test/reopen_test.rb +0 -22
@@ -1,7 +1,8 @@
1
1
  /*
2
2
  * libxlsxwriter
3
3
  *
4
- * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
4
+ * SPDX-License-Identifier: BSD-2-Clause
5
+ * Copyright 2014-2026, John McNamara, jmcnamara@cpan.org.
5
6
  *
6
7
  * styles - A libxlsxwriter library for creating Excel XLSX styles files.
7
8
  *
@@ -1,7 +1,8 @@
1
1
  /*
2
2
  * libxlsxwriter
3
3
  *
4
- * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
4
+ * SPDX-License-Identifier: BSD-2-Clause
5
+ * Copyright 2014-2026, John McNamara, jmcnamara@cpan.org.
5
6
  *
6
7
  * table - A libxlsxwriter library for creating Excel XLSX table files.
7
8
  *
@@ -1,7 +1,8 @@
1
1
  /*
2
2
  * libxlsxwriter
3
3
  *
4
- * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
4
+ * SPDX-License-Identifier: BSD-2-Clause
5
+ * Copyright 2014-2026, John McNamara, jmcnamara@cpan.org.
5
6
  *
6
7
  * theme - A libxlsxwriter library for creating Excel XLSX theme files.
7
8
  *
@@ -66,7 +66,7 @@
66
66
  #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC)))
67
67
  #define ftello64 _ftelli64
68
68
  #define fseeko64 _fseeki64
69
- #else // old MSC
69
+ #else /* old MSC */
70
70
  #define ftello64 ftell
71
71
  #define fseeko64 fseek
72
72
  #endif
@@ -150,7 +150,7 @@ typedef long (ZCALLBACK *tell_file_func) (voidpf opaque, voidpf stream)
150
150
  typedef long (ZCALLBACK *seek_file_func) (voidpf opaque, voidpf stream, uLong offset, int origin);
151
151
 
152
152
 
153
- /* here is the "old" 32 bits structure structure */
153
+ /* here is the "old" 32 bits structure */
154
154
  typedef struct zlib_filefunc_def_s
155
155
  {
156
156
  open_file_func zopen_file;
@@ -194,8 +194,8 @@ typedef struct zlib_filefunc64_32_def_s
194
194
 
195
195
  #define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
196
196
  #define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
197
- /*#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream))*/
198
- /*#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode))*/
197
+ /* #define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream)) */
198
+ /* #define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode)) */
199
199
  #define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream))
200
200
  #define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream))
201
201
 
@@ -49,7 +49,7 @@
49
49
  extern "C" {
50
50
  #endif
51
51
 
52
- /*#define HAVE_BZIP2*/
52
+ /* #define HAVE_BZIP2 */
53
53
 
54
54
  #ifndef _ZLIB_H
55
55
  #include "zlib.h"
@@ -190,9 +190,9 @@ extern int ZEXPORT zipOpenNewFileInZip64(zipFile file,
190
190
  filename : the filename in zip (if NULL, '-' without quote will be used
191
191
  *zipfi contain supplemental information
192
192
  if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
193
- contains the extrafield data the the local header
193
+ contains the extrafield data for the local header
194
194
  if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
195
- contains the extrafield data the the local header
195
+ contains the extrafield data for the global header
196
196
  if comment != NULL, comment contain the comment string
197
197
  method contain the compression method (0 for store, Z_DEFLATED for deflate)
198
198
  level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
@@ -1,7 +1,8 @@
1
1
  /*
2
2
  * libxlsxwriter
3
3
  *
4
- * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
4
+ * SPDX-License-Identifier: BSD-2-Clause
5
+ * Copyright 2014-2026, John McNamara, jmcnamara@cpan.org.
5
6
  */
6
7
 
7
8
  /**
@@ -9,7 +10,7 @@
9
10
  *
10
11
  * @brief Utility functions for libxlsxwriter.
11
12
  *
12
- * <!-- Copyright 2014-2022, John McNamara, jmcnamara@cpan.org -->
13
+ * <!-- Copyright 2014-2026, John McNamara, jmcnamara@cpan.org -->
13
14
  *
14
15
  */
15
16
 
@@ -195,8 +196,45 @@ uint16_t lxw_name_to_col_2(const char *col_str);
195
196
  */
196
197
  double lxw_datetime_to_excel_datetime(lxw_datetime *datetime);
197
198
 
198
- double lxw_datetime_to_excel_date_epoch(lxw_datetime *datetime,
199
- uint8_t date_1904);
199
+ /**
200
+ * @brief Converts a #lxw_datetime to an Excel datetime number with 1900/1904
201
+ * epoch.
202
+ *
203
+ * This function is similar to `lxw_datetime_to_excel_datetime()` but it allows
204
+ * you to specify whether to use the 1900 or 1904 epoch. See also the
205
+ * `workbook_use_1904_epoch()` function.
206
+ *
207
+ * @param datetime A pointer to a #lxw_datetime struct.
208
+ * @param use_1904_epoch A flag to indicate whether to use the 1904 epoch (true)
209
+ * or the 1900 epoch (false).
210
+ *
211
+ */
212
+ double lxw_datetime_to_excel_date_with_epoch(lxw_datetime *datetime,
213
+ uint8_t use_1904_epoch);
214
+
215
+ /**
216
+ * @brief Validate a #lxw_datetime struct.
217
+ *
218
+ * Validates a #lxw_datetime struct to ensure its fields are within acceptable
219
+ * ranges for Excel dates and times.
220
+ *
221
+ * The members of the #lxw_datetime struct and the range of their values are:
222
+ *
223
+ * Member | Value
224
+ * -------- | -----------
225
+ * year | 1900 - 9999
226
+ * month | 1 - 12
227
+ * day | 1 - 31
228
+ * hour | 0 - 23
229
+ * min | 0 - 59
230
+ * sec | 0 - 59.999
231
+ *
232
+ * @param datetime A pointer to a #lxw_datetime struct.
233
+ *
234
+ * @return A #lxw_error code. Either #LXW_NO_ERROR or
235
+ * #LXW_ERROR_DATETIME_VALIDATION if a field is out of range.
236
+ */
237
+ lxw_error lxw_datetime_validate(lxw_datetime *datetime);
200
238
 
201
239
  /**
202
240
  * @brief Converts a unix datetime to an Excel datetime number.
@@ -216,14 +254,27 @@ double lxw_datetime_to_excel_date_epoch(lxw_datetime *datetime,
216
254
  */
217
255
  double lxw_unixtime_to_excel_date(int64_t unixtime);
218
256
 
219
- double lxw_unixtime_to_excel_date_epoch(int64_t unixtime, uint8_t date_1904);
257
+ /**
258
+ * @brief Converts a unix datetime to an Excel datetime number with 1900/1904
259
+ * epoch.
260
+ *
261
+ * This function is similar to `lxw_unixtime_to_excel_date()` but it allows
262
+ * you to specify whether to use the 1900 or 1904 epoch. See also the
263
+ * `workbook_use_1904_epoch()` function.
264
+ *
265
+ * @param unixtime Unix time (seconds since 1970-01-01)
266
+ * @param use_1904_epoch A flag to indicate whether to use the 1904 epoch (true)
267
+ * or the 1900 epoch (false).
268
+ *
269
+ */
270
+ double lxw_unixtime_to_excel_date_with_epoch(int64_t unixtime,
271
+ uint8_t use_1904_epoch);
220
272
 
221
273
  char *lxw_strdup(const char *str);
222
274
  char *lxw_strdup_formula(const char *formula);
223
-
224
275
  size_t lxw_utf8_strlen(const char *str);
225
-
226
276
  void lxw_str_tolower(char *str);
277
+ uint8_t lxw_str_is_empty(const char *str);
227
278
 
228
279
  /* Define a portable version of strcasecmp(). */
229
280
  #ifdef _MSC_VER
@@ -1,7 +1,8 @@
1
1
  /*
2
2
  * libxlsxwriter
3
3
  *
4
- * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
4
+ * SPDX-License-Identifier: BSD-2-Clause
5
+ * Copyright 2014-2026, John McNamara, jmcnamara@cpan.org.
5
6
  *
6
7
  * vml - A libxlsxwriter library for creating Excel XLSX vml files.
7
8
  *
@@ -1,7 +1,8 @@
1
1
  /*
2
2
  * libxlsxwriter
3
3
  *
4
- * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
4
+ * SPDX-License-Identifier: BSD-2-Clause
5
+ * Copyright 2014-2026, John McNamara, jmcnamara@cpan.org.
5
6
  */
6
7
 
7
8
  /**
@@ -298,6 +299,7 @@ typedef struct lxw_workbook {
298
299
  struct lxw_worksheet_names *worksheet_names;
299
300
  struct lxw_chartsheet_names *chartsheet_names;
300
301
  struct lxw_image_md5s *image_md5s;
302
+ struct lxw_image_md5s *embedded_image_md5s;
301
303
  struct lxw_image_md5s *header_image_md5s;
302
304
  struct lxw_image_md5s *background_md5s;
303
305
  struct lxw_charts *charts;
@@ -321,6 +323,9 @@ typedef struct lxw_workbook {
321
323
  uint16_t num_format_count;
322
324
  uint16_t drawing_count;
323
325
  uint16_t comment_count;
326
+ uint32_t num_embedded_images;
327
+ uint16_t window_width;
328
+ uint16_t window_height;
324
329
 
325
330
  uint16_t font_count;
326
331
  uint16_t border_count;
@@ -336,6 +341,9 @@ typedef struct lxw_workbook {
336
341
  uint8_t has_vml;
337
342
  uint8_t has_comments;
338
343
  uint8_t has_metadata;
344
+ uint8_t has_embedded_images;
345
+ uint8_t has_dynamic_functions;
346
+ uint8_t has_embedded_image_descriptions;
339
347
 
340
348
  lxw_hash_table *used_xf_formats;
341
349
  lxw_hash_table *used_dxf_formats;
@@ -344,6 +352,8 @@ typedef struct lxw_workbook {
344
352
  char *vba_project_signature;
345
353
  char *vba_codename;
346
354
 
355
+ uint8_t use_1904_epoch;
356
+
347
357
  lxw_format *default_url_format;
348
358
 
349
359
  } lxw_workbook;
@@ -468,6 +478,7 @@ lxw_workbook *workbook_new_opt(const char *filename,
468
478
  *
469
479
  * The worksheet name must be a valid Excel worksheet name, i.e:
470
480
  *
481
+ * - The name cannot be blank.
471
482
  * - The name is less than or equal to 31 UTF-8 characters.
472
483
  * - The name doesn't contain any of the characters: ` [ ] : * ? / \ `
473
484
  * - The name doesn't start or end with an apostrophe.
@@ -510,6 +521,7 @@ lxw_worksheet *workbook_add_worksheet(lxw_workbook *workbook,
510
521
  *
511
522
  * The chartsheet name must be a valid Excel worksheet name, i.e.:
512
523
  *
524
+ * - The name cannot be blank.
513
525
  * - The name is less than or equal to 31 UTF-8 characters.
514
526
  * - The name doesn't contain any of the characters: ` [ ] : * ? / \ `
515
527
  * - The name doesn't start or end with an apostrophe.
@@ -859,7 +871,7 @@ lxw_error workbook_set_custom_property_datetime(lxw_workbook *workbook,
859
871
  * @endcode
860
872
  *
861
873
  * The rules for names in Excel are explained in the
862
- * [Microsoft Office documentation](http://office.microsoft.com/en-001/excel-help/define-and-use-names-in-formulas-HA010147120.aspx).
874
+ * [Microsoft Office documentation](https://support.microsoft.com/en-us/office/define-and-use-names-in-formulas-4d0f13ac-53b7-422e-afd2-abd7ff379c64).
863
875
  *
864
876
  */
865
877
  lxw_error workbook_define_name(lxw_workbook *workbook, const char *name,
@@ -932,6 +944,7 @@ lxw_chartsheet *workbook_get_chartsheet_by_name(lxw_workbook *workbook,
932
944
  * This function is used to validate a worksheet or chartsheet name according
933
945
  * to the rules used by Excel:
934
946
  *
947
+ * - The name cannot be blank.
935
948
  * - The name is less than or equal to 31 UTF-8 characters.
936
949
  * - The name doesn't contain any of the characters: ` [ ] : * ? / \ `
937
950
  * - The name doesn't start or end with an apostrophe.
@@ -1066,6 +1079,47 @@ lxw_error workbook_set_vba_name(lxw_workbook *workbook, const char *name);
1066
1079
  */
1067
1080
  void workbook_read_only_recommended(lxw_workbook *workbook);
1068
1081
 
1082
+ /**
1083
+ * @brief Set the workbook to use the 1904 epoch.
1084
+ *
1085
+ * @param workbook Pointer to a lxw_workbook instance.
1086
+ *
1087
+ * The `%workbook_use_1904_epoch()` function can be used to set the workbook to
1088
+ * use the 1904 epoch instead of the default 1900 epoch.
1089
+ *
1090
+ * Excel supports two date epochs. The first based on 1900-01-01 is the default
1091
+ * for all Windows versions of Excel and for recent versions of Excel for macOS.
1092
+ * Older versions of Excel for macOS used a 1904-01-01 epoch. The 1904 epoch can
1093
+ * be set for compatibility with older versions of Excel or to work around the
1094
+ * Excel limitation of not being able to handle negative times.
1095
+ *
1096
+ * This function should be called before `worksheet_add_worksheet()`.
1097
+ *
1098
+ * @code
1099
+ * workbook_use_1904_epoch(workbook);
1100
+ * @endcode
1101
+ *
1102
+ */
1103
+ void workbook_use_1904_epoch(lxw_workbook *workbook);
1104
+
1105
+ /**
1106
+ * @brief Set the size of a workbook window.
1107
+ *
1108
+ * @param workbook Pointer to a lxw_workbook instance.
1109
+ * @param width Width of the window in pixels.
1110
+ * @param height Height of the window in pixels.
1111
+ *
1112
+ * Set the size of a workbook window. This is generally only useful on macOS
1113
+ * since Microsoft Windows uses the window size from the last time an Excel file
1114
+ * was opened/saved. The default size is 1073 x 644 pixels.
1115
+ *
1116
+ * The resulting pixel sizes may not exactly match the target screen and
1117
+ * resolution since it is based on the original Excel for Windows sizes. Some
1118
+ * trial and error may be required to get an exact size.
1119
+ */
1120
+ void workbook_set_size(lxw_workbook *workbook,
1121
+ uint16_t width, uint16_t height);
1122
+
1069
1123
  void lxw_workbook_free(lxw_workbook *workbook);
1070
1124
  void lxw_workbook_assemble_xml_file(lxw_workbook *workbook);
1071
1125
  void lxw_workbook_set_default_xf_indices(lxw_workbook *workbook);
@@ -1094,6 +1148,9 @@ STATIC lxw_error _store_defined_name(lxw_workbook *self, const char *name,
1094
1148
  const char *formula, int16_t index,
1095
1149
  uint8_t hidden);
1096
1150
 
1151
+ STATIC lxw_error _get_image_properties(lxw_object_properties *image_props);
1152
+ STATIC void _free_object_properties(lxw_object_properties *object_property);
1153
+
1097
1154
  #endif /* TESTING */
1098
1155
 
1099
1156
  /* *INDENT-OFF* */
@@ -1,7 +1,8 @@
1
1
  /*
2
2
  * libxlsxwriter
3
3
  *
4
- * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
4
+ * SPDX-License-Identifier: BSD-2-Clause
5
+ * Copyright 2014-2026, John McNamara, jmcnamara@cpan.org.
5
6
  */
6
7
 
7
8
  /**
@@ -720,6 +721,7 @@ enum cell_types {
720
721
  DYNAMIC_ARRAY_FORMULA_CELL,
721
722
  BLANK_CELL,
722
723
  BOOLEAN_CELL,
724
+ ERROR_CELL,
723
725
  COMMENT,
724
726
  HYPERLINK_URL,
725
727
  HYPERLINK_INTERNAL,
@@ -817,6 +819,7 @@ STAILQ_HEAD(lxw_selections, lxw_selection);
817
819
  STAILQ_HEAD(lxw_data_validations, lxw_data_val_obj);
818
820
  STAILQ_HEAD(lxw_cond_format_list, lxw_cond_format_obj);
819
821
  STAILQ_HEAD(lxw_image_props, lxw_object_properties);
822
+ STAILQ_HEAD(lxw_embedded_image_props, lxw_object_properties);
820
823
  STAILQ_HEAD(lxw_chart_props, lxw_object_properties);
821
824
  STAILQ_HEAD(lxw_comment_objs, lxw_vml_obj);
822
825
  STAILQ_HEAD(lxw_table_objs, lxw_table_obj);
@@ -982,7 +985,7 @@ typedef struct lxw_data_validation {
982
985
  const char *value_formula;
983
986
 
984
987
  /**
985
- * This parameter is used to set a list of strings for a drop down list.
988
+ * This parameter is used to set a list of strings for a dropdown list.
986
989
  * The list should be a `NULL` terminated array of char* strings:
987
990
  *
988
991
  * @code
@@ -1695,8 +1698,8 @@ typedef struct lxw_filter_rule_obj {
1695
1698
  /**
1696
1699
  * @brief Options for inserted images.
1697
1700
  *
1698
- * Options for modifying images inserted via `worksheet_insert_image_opt()`.
1699
- *
1701
+ * Options for modifying images inserted via `worksheet_insert_image_opt()` and
1702
+ * `worksheet_embed_image_opt()`.
1700
1703
  */
1701
1704
  typedef struct lxw_image_options {
1702
1705
 
@@ -1735,6 +1738,10 @@ typedef struct lxw_image_options {
1735
1738
  /** Add an optional mouseover tip for a hyperlink to the image. */
1736
1739
  const char *tip;
1737
1740
 
1741
+ /** Add an optional format to the cell. Only used with
1742
+ * `worksheet_embed_image_opt()` */
1743
+ lxw_format *cell_format;
1744
+
1738
1745
  } lxw_image_options;
1739
1746
 
1740
1747
  /**
@@ -1806,6 +1813,7 @@ typedef struct lxw_object_properties {
1806
1813
  char *md5;
1807
1814
  char *image_position;
1808
1815
  uint8_t decorative;
1816
+ lxw_format *format;
1809
1817
 
1810
1818
  STAILQ_ENTRY (lxw_object_properties) list_pointers;
1811
1819
  } lxw_object_properties;
@@ -2119,6 +2127,7 @@ typedef struct lxw_worksheet {
2119
2127
  struct lxw_data_validations *data_validations;
2120
2128
  struct lxw_cond_format_hash *conditional_formats;
2121
2129
  struct lxw_image_props *image_props;
2130
+ struct lxw_image_props *embedded_image_props;
2122
2131
  struct lxw_chart_props *chart_data;
2123
2132
  struct lxw_drawing_rel_ids *drawing_rel_ids;
2124
2133
  struct lxw_vml_drawing_rel_ids *vml_drawing_rel_ids;
@@ -2192,7 +2201,7 @@ typedef struct lxw_worksheet {
2192
2201
  uint8_t zoom_scale_normal;
2193
2202
  uint8_t black_white;
2194
2203
  uint8_t num_validations;
2195
- uint8_t has_dynamic_arrays;
2204
+ uint8_t has_dynamic_functions;
2196
2205
  char *vba_codename;
2197
2206
  uint16_t num_buttons;
2198
2207
 
@@ -2251,6 +2260,7 @@ typedef struct lxw_worksheet {
2251
2260
  uint8_t has_header_vml;
2252
2261
  uint8_t has_background_image;
2253
2262
  uint8_t has_buttons;
2263
+ uint8_t storing_embedded_image;
2254
2264
  lxw_rel_tuple *external_vml_comment_link;
2255
2265
  lxw_rel_tuple *external_comment_link;
2256
2266
  lxw_rel_tuple *external_vml_header_link;
@@ -2275,6 +2285,8 @@ typedef struct lxw_worksheet {
2275
2285
  char *ignore_calculated_column;
2276
2286
  char *ignore_two_digit_text_year;
2277
2287
 
2288
+ uint8_t use_1904_epoch;
2289
+
2278
2290
  uint16_t excel_version;
2279
2291
 
2280
2292
  lxw_object_properties **header_footer_objs[LXW_HEADER_FOOTER_OBJS_MAX];
@@ -2308,6 +2320,7 @@ typedef struct lxw_worksheet_init_data {
2308
2320
  const char *tmpdir;
2309
2321
  lxw_format *default_url_format;
2310
2322
  uint16_t max_url_length;
2323
+ uint8_t use_1904_epoch;
2311
2324
 
2312
2325
  } lxw_worksheet_init_data;
2313
2326
 
@@ -3621,9 +3634,18 @@ lxw_error worksheet_set_column_pixels_opt(lxw_worksheet *worksheet,
3621
3634
  * **Note**:
3622
3635
  * The scaling of a image may be affected if is crosses a row that has its
3623
3636
  * default height changed due to a font that is larger than the default font
3624
- * size or that has text wrapping turned on. To avoid this you should
3625
- * explicitly set the height of the row using `worksheet_set_row()` if it
3626
- * crosses an inserted image. See @ref working_with_object_positioning.
3637
+ * size or that has text wrapping turned on. To avoid this you should explicitly
3638
+ * set the height of the row using `worksheet_set_row()` if it crosses an
3639
+ * inserted image. See @ref working_with_object_positioning.
3640
+ *
3641
+ * **NOTE on SVG files**:
3642
+ * Excel doesn't directly support SVG files in the same way as other image file
3643
+ * formats. It allows SVG to be inserted into a worksheet but converts them to,
3644
+ * and displays them as, PNG files. It stores the original SVG image in the file
3645
+ * so the original format can be retrieved. This removes the file size and
3646
+ * resolution advantage of using SVG files. As such SVG files are not supported
3647
+ * by `libxlsxwriter` since a conversion to the PNG format would be required
3648
+ * and that format is already supported.
3627
3649
  *
3628
3650
  * BMP images are only supported for backward compatibility. In general it is
3629
3651
  * best to avoid BMP images since they aren't compressed. If used, BMP images
@@ -3746,7 +3768,7 @@ lxw_error worksheet_insert_image_buffer(lxw_worksheet *worksheet,
3746
3768
  *
3747
3769
  * The `%worksheet_insert_image_buffer_opt()` function is like
3748
3770
  * `worksheet_insert_image_buffer()` function except that it takes an optional
3749
- * #lxw_image_options struct * #lxw_image_options struct with the following members/options:
3771
+ * #lxw_image_options struct with the following members/options:
3750
3772
  *
3751
3773
  * - `x_offset`: Offset from the left of the cell in pixels.
3752
3774
  * - `y_offset`: Offset from the top of the cell in pixels.
@@ -3782,6 +3804,126 @@ lxw_error worksheet_insert_image_buffer_opt(lxw_worksheet *worksheet,
3782
3804
  size_t image_size,
3783
3805
  lxw_image_options *options);
3784
3806
 
3807
+ /**
3808
+ * @brief Embed an image in a worksheet cell.
3809
+ *
3810
+ * @param worksheet Pointer to a lxw_worksheet instance to be updated.
3811
+ * @param row The zero indexed row number.
3812
+ * @param col The zero indexed column number.
3813
+ * @param filename The image filename, with path if required.
3814
+ *
3815
+ * @return A #lxw_error code.
3816
+ *
3817
+ * This function can be used to embed a image into a worksheet cell and have the
3818
+ * image automatically scale to the width and height of the cell. The X/Y
3819
+ * scaling of the image is preserved but the size of the image is adjusted to
3820
+ * fit the largest possible width or height depending on the cell dimensions.
3821
+ *
3822
+ * This is the equivalent of Excel's menu option to insert an image using the
3823
+ * option to "Place in Cell" which is only available in Excel 365 versions from
3824
+ * 2023 onwards. For older versions of Excel a `#VALUE!` error is displayed.
3825
+ *
3826
+ * @dontinclude embed_images.c
3827
+ * @skip Change
3828
+ * @until B6
3829
+ *
3830
+ * @image html embed_image.png
3831
+ *
3832
+ * The `worksheet_embed_image_opt()` function takes additional optional
3833
+ * parameters to add urls or format the cell background, see below.
3834
+ *
3835
+ */
3836
+ lxw_error worksheet_embed_image(lxw_worksheet *worksheet,
3837
+ lxw_row_t row, lxw_col_t col,
3838
+ const char *filename);
3839
+
3840
+ /**
3841
+ * @brief Embed an image in a worksheet cell, with options.
3842
+ *
3843
+ * @param worksheet Pointer to a lxw_worksheet instance to be updated.
3844
+ * @param row The zero indexed row number.
3845
+ * @param col The zero indexed column number.
3846
+ * @param filename The image filename, with path if required.
3847
+ * @param options Optional image parameters.
3848
+ *
3849
+ * @return A #lxw_error code.
3850
+ *
3851
+ * The `%worksheet_embed_image_opt()` function is like
3852
+ * `worksheet_embed_image()` function except that it takes an optional
3853
+ * #lxw_image_options struct with the following members/options:
3854
+ *
3855
+ * - `description`: Optional description or "Alt text" for the image.
3856
+ * - `decorative`: Optional parameter to mark image as decorative.
3857
+ * - `url`: Add an optional hyperlink to the image.
3858
+ * - `cell_format`: Add a format for the cell behind the embedded image.
3859
+ *
3860
+ */
3861
+ lxw_error worksheet_embed_image_opt(lxw_worksheet *worksheet,
3862
+ lxw_row_t row, lxw_col_t col,
3863
+ const char *filename,
3864
+ lxw_image_options *options);
3865
+
3866
+ /**
3867
+ * @brief Embed an image in a worksheet cell, from a memory buffer.
3868
+ *
3869
+ * @param worksheet Pointer to a lxw_worksheet instance to be updated.
3870
+ * @param row The zero indexed row number.
3871
+ * @param col The zero indexed column number.
3872
+ * @param image_buffer Pointer to an array of bytes that holds the image data.
3873
+ * @param image_size The size of the array of bytes.
3874
+ *
3875
+ * @return A #lxw_error code.
3876
+ *
3877
+ * This function can be used to embed a image into a worksheet from a memory
3878
+ * buffer:
3879
+ *
3880
+ * @dontinclude embed_image_buffer.c
3881
+ * @skip Embed
3882
+ * @until B3
3883
+ *
3884
+ * @image html embed_image_buffer.png
3885
+ *
3886
+ * The buffer should be a pointer to an array of unsigned char data with a
3887
+ * specified size.
3888
+ *
3889
+ * See `worksheet_embed_image()` for details about the supported image
3890
+ * formats, and other image features.
3891
+ */
3892
+ lxw_error worksheet_embed_image_buffer(lxw_worksheet *worksheet,
3893
+ lxw_row_t row,
3894
+ lxw_col_t col,
3895
+ const unsigned char *image_buffer,
3896
+ size_t image_size);
3897
+
3898
+ /**
3899
+ * @brief Embed an image in a worksheet cell, from a memory buffer.
3900
+ *
3901
+ * @param worksheet Pointer to a lxw_worksheet instance to be updated.
3902
+ * @param row The zero indexed row number.
3903
+ * @param col The zero indexed column number.
3904
+ * @param image_buffer Pointer to an array of bytes that holds the image data.
3905
+ * @param image_size The size of the array of bytes.
3906
+ * @param options Optional image parameters.
3907
+ *
3908
+ * @return A #lxw_error code.
3909
+ *
3910
+ * The `%worksheet_embed_image_buffer_opt()` function is like
3911
+ * `worksheet_embed_image_buffer()` function except that it takes an optional
3912
+ * #lxw_image_options struct with the following members/options:
3913
+ *
3914
+ * - `description`: Optional description or "Alt text" for the image.
3915
+ * - `decorative`: Optional parameter to mark image as decorative.
3916
+ * - `url`: Add an optional hyperlink to the image.
3917
+ * - `cell_format`: Add a format for the cell behind the embedded image.
3918
+ *
3919
+ */
3920
+ lxw_error worksheet_embed_image_buffer_opt(lxw_worksheet *worksheet,
3921
+ lxw_row_t row,
3922
+ lxw_col_t col,
3923
+ const unsigned char *image_buffer,
3924
+ size_t image_size,
3925
+ lxw_image_options *options);
3926
+
3785
3927
  /**
3786
3928
  * @brief Set the background image for a worksheet.
3787
3929
  *
@@ -3995,7 +4137,7 @@ lxw_error worksheet_merge_range(lxw_worksheet *worksheet, lxw_row_t first_row,
3995
4137
  * The `%worksheet_autofilter()` function allows an autofilter to be added to
3996
4138
  * a worksheet.
3997
4139
  *
3998
- * An autofilter is a way of adding drop down lists to the headers of a 2D
4140
+ * An autofilter is a way of adding dropdown lists to the headers of a 2D
3999
4141
  * range of worksheet data. This allows users to filter the data based on
4000
4142
  * simple criteria so that some data is shown and some is hidden.
4001
4143
  *
@@ -4578,9 +4720,9 @@ void worksheet_split_panes_opt(lxw_worksheet *worksheet,
4578
4720
  * @endcode
4579
4721
  *
4580
4722
  */
4581
- void worksheet_set_selection(lxw_worksheet *worksheet,
4582
- lxw_row_t first_row, lxw_col_t first_col,
4583
- lxw_row_t last_row, lxw_col_t last_col);
4723
+ lxw_error worksheet_set_selection(lxw_worksheet *worksheet,
4724
+ lxw_row_t first_row, lxw_col_t first_col,
4725
+ lxw_row_t last_row, lxw_col_t last_col);
4584
4726
 
4585
4727
  /**
4586
4728
  * @brief Set the first visible cell at the top left of a worksheet.
@@ -5811,6 +5953,10 @@ void lxw_worksheet_write_sheet_pr(lxw_worksheet *worksheet);
5811
5953
  void lxw_worksheet_write_page_setup(lxw_worksheet *worksheet);
5812
5954
  void lxw_worksheet_write_header_footer(lxw_worksheet *worksheet);
5813
5955
 
5956
+ void worksheet_set_error_cell(lxw_worksheet *worksheet,
5957
+ lxw_object_properties *object_props,
5958
+ uint32_t ref_id);
5959
+
5814
5960
  /* Declarations required for unit testing. */
5815
5961
  #ifdef TESTING
5816
5962