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
@@ -3,7 +3,8 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * SPDX-License-Identifier: BSD-2-Clause
7
+ * Copyright 2014-2026, John McNamara, jmcnamara@cpan.org.
7
8
  *
8
9
  */
9
10
 
@@ -27,16 +28,16 @@ STATIC char *_escape_attributes(struct xml_attribute *attribute);
27
28
 
28
29
  char *lxw_escape_data(const char *data);
29
30
 
30
- STATIC void _fprint_escaped_attributes(FILE * xmlfile,
31
+ STATIC void _fprint_escaped_attributes(FILE *xmlfile,
31
32
  struct xml_attribute_list *attributes);
32
33
 
33
- STATIC void _fprint_escaped_data(FILE * xmlfile, const char *data);
34
+ STATIC void _fprint_escaped_data(FILE *xmlfile, const char *data);
34
35
 
35
36
  /*
36
37
  * Write the XML declaration.
37
38
  */
38
39
  void
39
- lxw_xml_declaration(FILE * xmlfile)
40
+ lxw_xml_declaration(FILE *xmlfile)
40
41
  {
41
42
  fprintf(xmlfile, "<?xml version=\"1.0\" "
42
43
  "encoding=\"UTF-8\" standalone=\"yes\"?>\n");
@@ -46,7 +47,7 @@ lxw_xml_declaration(FILE * xmlfile)
46
47
  * Write an XML start tag with optional attributes.
47
48
  */
48
49
  void
49
- lxw_xml_start_tag(FILE * xmlfile,
50
+ lxw_xml_start_tag(FILE *xmlfile,
50
51
  const char *tag, struct xml_attribute_list *attributes)
51
52
  {
52
53
  fprintf(xmlfile, "<%s", tag);
@@ -61,7 +62,7 @@ lxw_xml_start_tag(FILE * xmlfile,
61
62
  * This is a minor speed optimization for elements that don't need encoding.
62
63
  */
63
64
  void
64
- lxw_xml_start_tag_unencoded(FILE * xmlfile,
65
+ lxw_xml_start_tag_unencoded(FILE *xmlfile,
65
66
  const char *tag,
66
67
  struct xml_attribute_list *attributes)
67
68
  {
@@ -82,7 +83,7 @@ lxw_xml_start_tag_unencoded(FILE * xmlfile,
82
83
  * Write an XML end tag.
83
84
  */
84
85
  void
85
- lxw_xml_end_tag(FILE * xmlfile, const char *tag)
86
+ lxw_xml_end_tag(FILE *xmlfile, const char *tag)
86
87
  {
87
88
  fprintf(xmlfile, "</%s>", tag);
88
89
  }
@@ -91,7 +92,7 @@ lxw_xml_end_tag(FILE * xmlfile, const char *tag)
91
92
  * Write an empty XML tag with optional attributes.
92
93
  */
93
94
  void
94
- lxw_xml_empty_tag(FILE * xmlfile,
95
+ lxw_xml_empty_tag(FILE *xmlfile,
95
96
  const char *tag, struct xml_attribute_list *attributes)
96
97
  {
97
98
  fprintf(xmlfile, "<%s", tag);
@@ -106,7 +107,7 @@ lxw_xml_empty_tag(FILE * xmlfile,
106
107
  * This is a minor speed optimization for elements that don't need encoding.
107
108
  */
108
109
  void
109
- lxw_xml_empty_tag_unencoded(FILE * xmlfile,
110
+ lxw_xml_empty_tag_unencoded(FILE *xmlfile,
110
111
  const char *tag,
111
112
  struct xml_attribute_list *attributes)
112
113
  {
@@ -127,7 +128,7 @@ lxw_xml_empty_tag_unencoded(FILE * xmlfile,
127
128
  * Write an XML element containing data with optional attributes.
128
129
  */
129
130
  void
130
- lxw_xml_data_element(FILE * xmlfile,
131
+ lxw_xml_data_element(FILE *xmlfile,
131
132
  const char *tag,
132
133
  const char *data, struct xml_attribute_list *attributes)
133
134
  {
@@ -146,7 +147,7 @@ lxw_xml_data_element(FILE * xmlfile,
146
147
  * Write an XML <si> element for rich strings, without encoding.
147
148
  */
148
149
  void
149
- lxw_xml_rich_si_element(FILE * xmlfile, const char *string)
150
+ lxw_xml_rich_si_element(FILE *xmlfile, const char *string)
150
151
  {
151
152
  fprintf(xmlfile, "<si>%s</si>", string);
152
153
  }
@@ -238,7 +239,7 @@ lxw_escape_data(const char *data)
238
239
  uint8_t
239
240
  lxw_has_control_characters(const char *string)
240
241
  {
241
- while (string) {
242
+ while (*string) {
242
243
  /* 0xE0 == 0b11100000 masks values > 0x19 == 0b00011111. */
243
244
  if (!(*string & 0xE0) && *string != 0x0A && *string != 0x09)
244
245
  return LXW_TRUE;
@@ -369,7 +370,7 @@ lxw_escape_url_characters(const char *string, uint8_t escape_hash)
369
370
 
370
371
  /* Write out escaped attributes. */
371
372
  STATIC void
372
- _fprint_escaped_attributes(FILE * xmlfile,
373
+ _fprint_escaped_attributes(FILE *xmlfile,
373
374
  struct xml_attribute_list *attributes)
374
375
  {
375
376
  struct xml_attribute *attribute;
@@ -396,7 +397,7 @@ _fprint_escaped_attributes(FILE * xmlfile,
396
397
 
397
398
  /* Write out escaped XML data. */
398
399
  STATIC void
399
- _fprint_escaped_data(FILE * xmlfile, const char *data)
400
+ _fprint_escaped_data(FILE *xmlfile, const char *data)
400
401
  {
401
402
  /* Escape the data section of the XML element. */
402
403
  if (!strpbrk(data, "&<>")) {
@@ -425,18 +426,12 @@ lxw_new_attribute_str(const char *key, const char *value)
425
426
 
426
427
  /* Create a new integer XML attribute. */
427
428
  struct xml_attribute *
428
- lxw_new_attribute_int(const char *key, uint64_t value)
429
+ lxw_new_attribute_int(const char *key, int32_t value)
429
430
  {
430
431
  struct xml_attribute *attribute = malloc(sizeof(struct xml_attribute));
431
432
 
432
433
  LXW_ATTRIBUTE_COPY(attribute->key, key);
433
-
434
- #if defined(_MSC_VER)
435
- lxw_snprintf(attribute->value, LXW_MAX_ATTRIBUTE_LENGTH, "%lld", value);
436
- #else
437
- lxw_snprintf(attribute->value, LXW_MAX_ATTRIBUTE_LENGTH, "%ld",
438
- (long) value);
439
- #endif
434
+ lxw_snprintf(attribute->value, LXW_MAX_ATTRIBUTE_LENGTH, "%d", value);
440
435
 
441
436
  return attribute;
442
437
  }
@@ -1,4 +1,4 @@
1
- CC=cc
1
+ CC?=cc
2
2
  CFLAGS := $(CFLAGS) -O -I../..
3
3
 
4
4
  UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a
@@ -1,7 +1,7 @@
1
1
  # -*- Autoconf -*-
2
2
  # Process this file with autoconf to produce a configure script.
3
3
 
4
- AC_INIT([minizip], [1.3.0], [bugzilla.redhat.com])
4
+ AC_INIT([minizip], [1.3.1], [bugzilla.redhat.com])
5
5
  AC_CONFIG_SRCDIR([minizip.c])
6
6
  AM_INIT_AUTOMAKE([foreign])
7
7
  LT_INIT
@@ -29,8 +29,8 @@
29
29
 
30
30
  #if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
31
31
 
32
- // Linux needs this to support file operation on files larger then 4+GB
33
- // But might need better if/def to select just the platforms that needs them.
32
+ /* Linux needs this to support file operation on files larger then 4+GB
33
+ * But might need better if/def to select just the platforms that needs them. */
34
34
 
35
35
  #ifndef __USE_FILE_OFFSET64
36
36
  #define __USE_FILE_OFFSET64
@@ -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
 
@@ -79,7 +79,7 @@
79
79
 
80
80
  /* change_file_date : change the date/time of a file
81
81
  filename : the filename of the file where date/time must be modified
82
- dosdate : the new date at the MSDos format (4 bytes)
82
+ dosdate : the new date at the MSDOS format (4 bytes)
83
83
  tmu_date : the SAME new date at the tm_unz format */
84
84
  static void change_file_date(const char *filename, uLong dosdate, tm_unz tmu_date) {
85
85
  #ifdef _WIN32
@@ -186,7 +186,7 @@ static int makedir(const char *newdir) {
186
186
  }
187
187
 
188
188
  static void do_banner(void) {
189
- printf("MiniUnz 1.01b, demo of zLib + Unz package written by Gilles Vollant\n");
189
+ printf("MiniUnz 1.1, demo of zLib + Unz package written by Gilles Vollant\n");
190
190
  printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n");
191
191
  }
192
192
 
@@ -356,6 +356,20 @@ static int do_extract_currentfile(unzFile uf, const int* popt_extract_without_pa
356
356
  else
357
357
  write_filename = filename_withoutpath;
358
358
 
359
+ if (write_filename[0]!='\0')
360
+ {
361
+ const char* relative_check = write_filename;
362
+ while (relative_check[1]!='\0')
363
+ {
364
+ if (relative_check[0]=='.' && relative_check[1]=='.')
365
+ write_filename = relative_check;
366
+ relative_check++;
367
+ }
368
+ }
369
+
370
+ while (write_filename[0]=='/' || write_filename[0]=='.')
371
+ write_filename++;
372
+
359
373
  err = unzOpenCurrentFilePassword(uf,password);
360
374
  if (err!=UNZ_OK)
361
375
  {
@@ -117,7 +117,7 @@
117
117
  const char unz_copyright[] =
118
118
  " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
119
119
 
120
- /* unz_file_info_interntal contain internal info about a file in zipfile*/
120
+ /* unz_file_info64_internal contain internal info about a file in zipfile*/
121
121
  typedef struct unz_file_info64_internal_s
122
122
  {
123
123
  ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */
@@ -450,7 +450,7 @@ local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib
450
450
  if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
451
451
  return CENTRALDIRINVALID;
452
452
 
453
- /* number of the disk with the start of the zip64 end of central directory */
453
+ /* number of the disk with the start of the zip64 end of central directory */
454
454
  if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
455
455
  return CENTRALDIRINVALID;
456
456
  if (uL != 0)
@@ -497,9 +497,9 @@ local unzFile unzOpenInternal(const void *path,
497
497
  ZPOS64_T central_pos;
498
498
  uLong uL;
499
499
 
500
- uLong number_disk; /* number of the current dist, used for
500
+ uLong number_disk; /* number of the current disk, used for
501
501
  spanning ZIP, unsupported, always 0*/
502
- uLong number_disk_with_CD; /* number the the disk with central dir, used
502
+ uLong number_disk_with_CD; /* number the disk with central dir, used
503
503
  for spanning ZIP, unsupported, always 0*/
504
504
  ZPOS64_T number_entry_CD; /* total number of entries in
505
505
  the central dir
@@ -306,7 +306,7 @@ extern int ZEXPORT unzGetCurrentFileInfo(unzFile file,
306
306
  Get Info about the current file
307
307
  if pfile_info!=NULL, the *pfile_info structure will contain some info about
308
308
  the current file
309
- if szFileName!=NULL, the filemane string will be copied in szFileName
309
+ if szFileName!=NULL, the filename string will be copied in szFileName
310
310
  (fileNameBufferSize is the size of the buffer)
311
311
  if extraField!=NULL, the extra field information will be copied in extraField
312
312
  (extraFieldBufferSize is the size of the buffer).
@@ -575,7 +575,7 @@ local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib
575
575
  if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
576
576
  return 0;
577
577
 
578
- /* number of the disk with the start of the zip64 end of central directory */
578
+ /* number of the disk with the start of the zip64 end of central directory */
579
579
  if (zip64local_getLong(pzlib_filefunc_def,filestream,&uL)!=ZIP_OK)
580
580
  return 0;
581
581
  if (uL != 0)
@@ -614,9 +614,9 @@ local int LoadCentralDirectoryRecord(zip64_internal* pziinit) {
614
614
  ZPOS64_T central_pos;
615
615
  uLong uL;
616
616
 
617
- uLong number_disk; /* number of the current dist, used for
617
+ uLong number_disk; /* number of the current disk, used for
618
618
  spanning ZIP, unsupported, always 0*/
619
- uLong number_disk_with_CD; /* number the the disk with central dir, used
619
+ uLong number_disk_with_CD; /* number of the disk with central dir, used
620
620
  for spanning ZIP, unsupported, always 0*/
621
621
  ZPOS64_T number_entry;
622
622
  ZPOS64_T number_entry_CD; /* total number of entries in
@@ -1608,7 +1608,7 @@ extern int ZEXPORT zipCloseFileInZipRaw64(zipFile file, ZPOS64_T uncompressed_si
1608
1608
 
1609
1609
  if((uLong)(datasize + 4) > zi->ci.size_centralExtraFree)
1610
1610
  {
1611
- // we can not write more data to the buffer that we have room for.
1611
+ // we cannot write more data to the buffer that we have room for.
1612
1612
  return ZIP_BADZIPFILE;
1613
1613
  }
1614
1614
 
@@ -1872,7 +1872,7 @@ extern int ZEXPORT zipClose(zipFile file, const char* global_comment) {
1872
1872
  free_linkedlist(&(zi->central_dir));
1873
1873
 
1874
1874
  pos = centraldir_pos_inzip - zi->add_position_when_writing_offset;
1875
- if(pos >= 0xffffffff || zi->number_entry > 0xFFFF)
1875
+ if(pos >= 0xffffffff || zi->number_entry >= 0xFFFF)
1876
1876
  {
1877
1877
  ZPOS64_T Zip64EOCDpos = ZTELL64(zi->z_filefunc,zi->filestream);
1878
1878
  Write_Zip64EndOfCentralDirectoryRecord(zi, size_centraldir, centraldir_pos_inzip);
@@ -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 +1 @@
1
- 2023-12-29 19:18:35 +0700 e3ede9d
1
+ 2026-10-19 01:47:16 +0400 db95245
@@ -0,0 +1,4 @@
1
+ sonar.sources=.
2
+ sonar.language=ruby
3
+ sonar.ruby.coverage.reportPaths=coverage/.resultset.json
4
+ sonar.exclusions=**/*_test.rb,**/coverage/**
@@ -0,0 +1,15 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe "FastExcel.color_to_hex" do
4
+ it "should convert hex number color to hex" do
5
+ assert_equal(FastExcel.color_to_hex(0xFF0000), 0xFF0000)
6
+ end
7
+
8
+ it "should convert color name to hex" do
9
+ assert_equal(FastExcel.color_to_hex("color_lime"), 0x00FF00)
10
+ end
11
+
12
+ it "should convert color name (extra colors) to hex" do
13
+ assert_equal(FastExcel.color_to_hex("steel_blue"), 0x4682B4)
14
+ end
15
+ end
@@ -0,0 +1,76 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe 'FastExcel::Worksheet write_comment_opt' do
4
+ let(:workbook) { FastExcel.open(constant_memory: true) }
5
+ let(:worksheet) { workbook.add_worksheet }
6
+ let(:options) do
7
+ Libxlsxwriter::CommentOptions.new.tap do |opts|
8
+ opts.author = 'Lolo'
9
+ opts.visible = 1
10
+ opts.width = 200
11
+ opts.height = 100
12
+ opts.x_scale = 1.5
13
+ opts.y_scale = 1.5
14
+ opts.color = '0xFFFF00'
15
+ opts.font_name = 'Arial'
16
+ opts.font_size = 12.0
17
+ opts.font_family = 2
18
+ opts.start_row = 0
19
+ opts.start_col = 1
20
+ opts.x_offset = 10
21
+ opts.y_offset = 10
22
+ end
23
+ end
24
+
25
+ it 'should write a comment with options struct' do
26
+ assert_equal(:no_error, worksheet.write_comment_opt(0, 0, 'Hello with options', options))
27
+ end
28
+
29
+ it 'should write a comment with hash options' do
30
+ assert_equal(:no_error, worksheet.write_comment_opt(1, 0, 'Comment via hash', author: 'Author1', visible: 1, color: '#FF0000'))
31
+ end
32
+
33
+ it 'should write a comment using write_comment with optional options' do
34
+ assert_equal(:no_error, worksheet.write_comment(2, 0, 'Simple comment'))
35
+ assert_equal(:no_error, worksheet.write_comment(3, 0, 'Comment with hash', author: 'Alice', color: 'lime'))
36
+ end
37
+
38
+ it 'handles nil author and font_name safely' do
39
+ opts = Libxlsxwriter::CommentOptions.new
40
+ opts.author = nil
41
+ opts.font_name = nil
42
+ assert_nil opts.author
43
+ assert_nil opts.font_name
44
+
45
+ opts.author = 'Bob'
46
+ assert_equal 'Bob', opts.author
47
+ opts.author = nil
48
+ assert_nil opts.author
49
+ end
50
+
51
+ it 'preserves string pointers across garbage collection' do
52
+ opts = Libxlsxwriter::CommentOptions.new(author: "Temporary #{rand} Author", font_name: 'Courier New')
53
+ # Run full GC cycles to ensure MemoryPointer is not collected prematurely
54
+ 10.times { GC.start }
55
+
56
+ assert opts.author.start_with?('Temporary')
57
+ assert_equal 'Courier New', opts.font_name
58
+ assert_equal :no_error, worksheet.write_comment_opt(4, 0, 'GC test comment', opts)
59
+ end
60
+
61
+ it 'generates a valid excel file with styled comments' do
62
+ temp_file = File.join(Dir.tmpdir, "test_comments_#{Time.now.to_i}.xlsx")
63
+ begin
64
+ wb = FastExcel.open(temp_file)
65
+ ws = wb.add_worksheet
66
+ ws.write_value(0, 0, 'Data')
67
+ ws.write_comment(0, 0, 'Styled comment', author: 'Tester', visible: 1, color: 'yellow', font_name: 'Arial')
68
+ wb.close
69
+
70
+ assert File.exist?(temp_file)
71
+ assert File.size(temp_file) > 0
72
+ ensure
73
+ File.delete(temp_file) if File.exist?(temp_file)
74
+ end
75
+ end
76
+ end
data/test/date_test.rb CHANGED
@@ -54,3 +54,17 @@ describe "FastExcel.write_value" do
54
54
  end
55
55
 
56
56
  end
57
+
58
+ describe "FastExcel.lxw_time" do
59
+ it "should make Libxlsxwriter::Datetime" do
60
+ time = Time.at(610421163).utc
61
+ lxw_time = FastExcel.lxw_time(time)
62
+
63
+ assert_equal(lxw_time[:year], 1989)
64
+ assert_equal(lxw_time[:month], 5)
65
+ assert_equal(lxw_time[:day], 6)
66
+ assert_equal(lxw_time[:hour], 1)
67
+ assert_equal(lxw_time[:min], 26)
68
+ assert_equal(lxw_time[:sec], 3.0)
69
+ end
70
+ end
data/test/format_test.rb CHANGED
@@ -112,7 +112,11 @@ describe "FastExcel::FormatExt colors" do
112
112
  @format.font_color = {aaa: 1}
113
113
  end
114
114
 
115
- assert_equal(error.message, "Can not use Hash ({:aaa=>1}) for color value, expected String or Hex Number")
115
+ if error.message =~ /=>/
116
+ assert_equal(error.message, "Can not use Hash ({:aaa=>1}) for color value, expected String or Hex Number")
117
+ else
118
+ assert_equal(error.message, "Can not use Hash ({aaa: 1}) for color value, expected String or Hex Number")
119
+ end
116
120
  end
117
121
 
118
122
  it "should raise for unexpected color" do
@@ -0,0 +1,28 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe "FastExcel::Worksheet" do
4
+ before do
5
+ @workbook = FastExcel.open(constant_memory: true)
6
+ end
7
+
8
+ describe "#get_worksheet_by_name" do
9
+ it "should return nil if worksheet does not exist" do
10
+ ws = @workbook.get_worksheet_by_name("Page1")
11
+ assert_nil(ws)
12
+
13
+ assert_nil(@workbook.get_worksheet_by_name(nil))
14
+ assert_nil(@workbook.get_worksheet_by_name(:Page1))
15
+ end
16
+
17
+ it "should return worksheet if worksheet does exist" do
18
+ @workbook.add_worksheet("Page1")
19
+
20
+ ws = @workbook.get_worksheet_by_name("Page1")
21
+ ws.write_row(0, ['1'])
22
+ assert_kind_of(Libxlsxwriter::Worksheet, ws)
23
+
24
+ ws_by_sym = @workbook.get_worksheet_by_name(:Page1)
25
+ assert_kind_of(Libxlsxwriter::Worksheet, ws_by_sym)
26
+ end
27
+ end
28
+ end
data/test/test_helper.rb CHANGED
@@ -1,13 +1,16 @@
1
+ require "simplecov"
2
+
3
+ SimpleCov.start do
4
+ add_filter 'test'
5
+ end
6
+
1
7
  require 'bundler/setup'
2
8
  require 'minitest/autorun'
3
9
  require "minitest/reporters"
4
10
  require 'pp'
5
-
6
- ##Encoding.default_external = Encoding::UTF_8
7
- ##Encoding.default_internal = Encoding::UTF_8
8
-
9
11
  require 'date'
10
12
 
13
+
11
14
  Minitest::Reporters.use!(
12
15
  Minitest::Reporters::DefaultReporter.new(color: true)
13
16
  )
@@ -0,0 +1,32 @@
1
+ require_relative 'test_helper'
2
+ require 'tmpdir'
3
+
4
+ describe "FastExcel tmpdir option" do
5
+ it "uses system Dir.tmpdir by default without creating extra temp directories" do
6
+ temp_file = File.join(Dir.tmpdir, "test_default_tmpdir_#{Time.now.to_i}.xlsx")
7
+ begin
8
+ wb = FastExcel.open(temp_file, constant_memory: true)
9
+ ws = wb.add_worksheet
10
+ ws.append_row(["test", 123])
11
+ wb.close
12
+
13
+ assert File.exist?(temp_file)
14
+ assert File.size(temp_file) > 0
15
+ ensure
16
+ File.delete(temp_file) if File.exist?(temp_file)
17
+ end
18
+ end
19
+
20
+ it "accepts custom tmpdir option" do
21
+ Dir.mktmpdir do |custom_tmp|
22
+ temp_file = File.join(custom_tmp, "test_custom_tmpdir.xlsx")
23
+ wb = FastExcel.open(temp_file, constant_memory: true, tmpdir: custom_tmp)
24
+ ws = wb.add_worksheet
25
+ ws.append_row(["hello", "world"])
26
+ wb.close
27
+
28
+ assert File.exist?(temp_file)
29
+ assert File.size(temp_file) > 0
30
+ end
31
+ end
32
+ end
@@ -2,23 +2,23 @@ require_relative 'test_helper'
2
2
 
3
3
  describe "FastExcel validations" do
4
4
 
5
- it "should raise error when duplicate sheet name" do
6
- workbook = FastExcel.open(constant_memory: true)
5
+ before do
6
+ @workbook = FastExcel.open(constant_memory: true)
7
+ end
7
8
 
8
- workbook.add_worksheet("Payments Report")
9
+ it "should raise error when duplicate sheet name" do
10
+ @workbook.add_worksheet("Payments Report")
9
11
  error = assert_raises do
10
- workbook.add_worksheet("Payments Report")
12
+ @workbook.add_worksheet("Payments Report")
11
13
  end
12
14
 
13
15
  assert_equal(ArgumentError, error.class)
14
- assert_equal("Invalid worksheet name 'Payments Report': (17 - error_sheetname_already_used) Worksheet name is already in use.", error.message)
16
+ assert_equal("Invalid worksheet name 'Payments Report': (19 - error_sheetname_already_used) Worksheet name is already in use.", error.message)
15
17
  end
16
18
 
17
19
  it "should not raise error when worksheet name is null" do
18
- workbook = FastExcel.open(constant_memory: true)
19
-
20
- ws1 = workbook.add_worksheet()
21
- ws2 = workbook.add_worksheet()
20
+ ws1 = @workbook.add_worksheet()
21
+ ws2 = @workbook.add_worksheet()
22
22
  ws2.write_value(0, 2, "aaa")
23
23
 
24
24
  assert_equal("Sheet1", ws1[:name])
@@ -26,33 +26,39 @@ describe "FastExcel validations" do
26
26
  end
27
27
 
28
28
  it "should raise error when the sheet name exceeds maximum length" do
29
- workbook = FastExcel.open(constant_memory: true)
30
-
31
29
  error = assert_raises do
32
- workbook.add_worksheet("ABCDEFGHIJKLMNOPQRSTUVWXYZ012345")
30
+ @workbook.add_worksheet("ABCDEFGHIJKLMNOPQRSTUVWXYZ012345")
33
31
  end
34
32
 
35
33
  assert_equal(ArgumentError, error.class)
36
- assert_equal("Invalid worksheet name 'ABCDEFGHIJKLMNOPQRSTUVWXYZ012345': (14 - error_sheetname_length_exceeded) Worksheet name exceeds Excel's limit of 31 characters.", error.message)
34
+ assert_equal("Invalid worksheet name 'ABCDEFGHIJKLMNOPQRSTUVWXYZ012345': (16 - error_sheetname_length_exceeded) Worksheet name exceeds Excel's limit of 31 characters.", error.message)
37
35
  end
38
36
 
39
37
  it "should not raise error when the sheet name is at maximum length" do
40
- workbook = FastExcel.open(constant_memory: true)
41
-
42
- worksheet = workbook.add_worksheet("ABCDEFGHIJKLMNOPQRSTUVWXYZ01234")
38
+ worksheet = @workbook.add_worksheet("ABCDEFGHIJKLMNOPQRSTUVWXYZ01234")
43
39
  worksheet.append_row(["aaa", "bbb", "ccc"])
44
40
 
45
41
  assert_equal("ABCDEFGHIJKLMNOPQRSTUVWXYZ01234", worksheet[:name])
46
42
  end
47
43
 
48
44
  it "should validate using Libxlsxwriter validation" do
49
- workbook = FastExcel.open(constant_memory: true)
50
45
  error = assert_raises do
51
- worksheet = workbook.add_worksheet('a?')
46
+ worksheet = @workbook.add_worksheet('a?')
52
47
  worksheet.write_value(1, 1, 'a') # without the validation, this method will crash the process
53
48
  end
54
49
 
55
50
  assert_equal(ArgumentError, error.class)
56
- assert_equal("Invalid worksheet name 'a?': (15 - error_invalid_sheetname_character) Worksheet name cannot contain invalid characters: '[ ] : * ? / \\'", error.message)
51
+ assert_equal("Invalid worksheet name 'a?': (17 - error_invalid_sheetname_character) Worksheet name cannot contain invalid characters: '[ ] : * ? / \\'", error.message)
52
+ end
53
+
54
+ it "should raise error when reopening workbook" do
55
+ @workbook.close
56
+
57
+ error = assert_raises do
58
+ FastExcel.open(@workbook.filename, constant_memory: true)
59
+ end
60
+
61
+ assert_equal(error.class, ArgumentError)
62
+ assert_equal(error.message, "File '#{@workbook.filename}' already exists. FastExcel can not open existing files, only create new files")
57
63
  end
58
64
  end
@@ -87,10 +87,18 @@ describe "FastExcel::WorksheetExt append_row" do
87
87
  it "should set name correctly" do
88
88
  workbook = FastExcel.open(constant_memory: true)
89
89
  ws1 = workbook.add_worksheet("foo")
90
- ws2 = workbook.add_worksheet("")
90
+ ws2 = workbook.add_worksheet
91
91
 
92
92
  assert_equal("foo", ws1[:name])
93
- assert_equal("", ws2[:name])
93
+ assert_equal("Sheet2", ws2[:name])
94
+ end
95
+
96
+ it "should raise error when sheet name is empty string" do
97
+ workbook = FastExcel.open(constant_memory: true)
98
+ error = assert_raises(ArgumentError) do
99
+ workbook.add_worksheet("")
100
+ end
101
+ assert_match(/error_parameter_is_empty/, error.message)
94
102
  end
95
103
 
96
104
  it "should map fields correctly" do