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.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +5 -1
- data/.gitignore +3 -0
- data/.octocov.yml +28 -0
- data/CHANGELOG.md +9 -0
- data/Gemfile +4 -2
- data/Rakefile +4 -1
- data/examples/comment_options.rb +39 -0
- data/fast_excel.gemspec +3 -2
- data/lib/fast_excel/binding/workbook.rb +53 -6
- data/lib/fast_excel/binding/worksheet.rb +28 -4
- data/lib/fast_excel/binding.rb +116 -13
- data/lib/fast_excel.rb +13 -12
- data/libxlsxwriter/.cirrus.yml +9 -0
- data/libxlsxwriter/.github/workflows/cmake_actions.yml +10 -6
- data/libxlsxwriter/.github/workflows/code_style.yml +2 -0
- data/libxlsxwriter/.github/workflows/make_32_actions.yml +43 -0
- data/libxlsxwriter/.github/workflows/windows_build.yml +7 -6
- data/libxlsxwriter/.github/workflows/zig_build.yml +1 -3
- data/libxlsxwriter/.gitignore +9 -7
- data/libxlsxwriter/.indent.pro +6 -0
- data/libxlsxwriter/CMakeLists.txt +377 -238
- data/libxlsxwriter/Changes.txt +189 -0
- data/libxlsxwriter/LICENSE.txt +1 -1
- data/libxlsxwriter/Makefile +36 -4
- data/libxlsxwriter/Readme.md +1 -1
- data/libxlsxwriter/build.zig +181 -92
- data/libxlsxwriter/build.zig.zon +15 -4
- data/libxlsxwriter/cocoapods/libxlsxwriter-umbrella.h +4 -0
- data/libxlsxwriter/include/xlsxwriter/app.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/chart.h +134 -1
- data/libxlsxwriter/include/xlsxwriter/chartsheet.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/comment.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/common.h +12 -8
- data/libxlsxwriter/include/xlsxwriter/content_types.h +3 -1
- data/libxlsxwriter/include/xlsxwriter/core.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/custom.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/drawing.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/format.h +34 -3
- data/libxlsxwriter/include/xlsxwriter/hash_table.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/metadata.h +5 -1
- data/libxlsxwriter/include/xlsxwriter/packager.h +6 -1
- data/libxlsxwriter/include/xlsxwriter/relationships.h +3 -1
- data/libxlsxwriter/include/xlsxwriter/rich_value.h +51 -0
- data/libxlsxwriter/include/xlsxwriter/rich_value_rel.h +50 -0
- data/libxlsxwriter/include/xlsxwriter/rich_value_structure.h +53 -0
- data/libxlsxwriter/include/xlsxwriter/rich_value_types.h +49 -0
- data/libxlsxwriter/include/xlsxwriter/shared_strings.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/styles.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/table.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/theme.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/third_party/ioapi.h +4 -4
- data/libxlsxwriter/include/xlsxwriter/third_party/zip.h +3 -3
- data/libxlsxwriter/include/xlsxwriter/utility.h +58 -7
- data/libxlsxwriter/include/xlsxwriter/vml.h +2 -1
- data/libxlsxwriter/include/xlsxwriter/workbook.h +59 -2
- data/libxlsxwriter/include/xlsxwriter/worksheet.h +159 -13
- data/libxlsxwriter/include/xlsxwriter/xmlwriter.h +11 -10
- data/libxlsxwriter/include/xlsxwriter.h +5 -4
- data/libxlsxwriter/libxlsxwriter.podspec +6 -6
- data/libxlsxwriter/src/Makefile +2 -1
- data/libxlsxwriter/src/app.c +2 -1
- data/libxlsxwriter/src/chart.c +360 -63
- data/libxlsxwriter/src/chartsheet.c +2 -1
- data/libxlsxwriter/src/comment.c +2 -1
- data/libxlsxwriter/src/content_types.c +22 -1
- data/libxlsxwriter/src/core.c +2 -1
- data/libxlsxwriter/src/custom.c +2 -1
- data/libxlsxwriter/src/drawing.c +7 -3
- data/libxlsxwriter/src/format.c +21 -1
- data/libxlsxwriter/src/hash_table.c +2 -1
- data/libxlsxwriter/src/metadata.c +176 -20
- data/libxlsxwriter/src/packager.c +306 -6
- data/libxlsxwriter/src/relationships.c +25 -1
- data/libxlsxwriter/src/rich_value.c +191 -0
- data/libxlsxwriter/src/rich_value_rel.c +142 -0
- data/libxlsxwriter/src/rich_value_structure.c +162 -0
- data/libxlsxwriter/src/rich_value_types.c +199 -0
- data/libxlsxwriter/src/shared_strings.c +2 -1
- data/libxlsxwriter/src/styles.c +31 -7
- data/libxlsxwriter/src/table.c +2 -1
- data/libxlsxwriter/src/theme.c +2 -1
- data/libxlsxwriter/src/utility.c +136 -46
- data/libxlsxwriter/src/vml.c +2 -1
- data/libxlsxwriter/src/workbook.c +191 -10
- data/libxlsxwriter/src/worksheet.c +514 -34
- data/libxlsxwriter/src/xmlwriter.c +17 -22
- data/libxlsxwriter/third_party/minizip/Makefile.orig +1 -1
- data/libxlsxwriter/third_party/minizip/configure.ac +1 -1
- data/libxlsxwriter/third_party/minizip/ioapi.h +6 -6
- data/libxlsxwriter/third_party/minizip/miniunz.c +16 -2
- data/libxlsxwriter/third_party/minizip/unzip.c +4 -4
- data/libxlsxwriter/third_party/minizip/unzip.h +1 -1
- data/libxlsxwriter/third_party/minizip/zip.c +5 -5
- data/libxlsxwriter/third_party/minizip/zip.h +3 -3
- data/libxlsxwriter/version.txt +1 -1
- data/sonar-project.properties +4 -0
- data/test/color_to_hex_test.rb +15 -0
- data/test/comment_opt_test.rb +76 -0
- data/test/date_test.rb +14 -0
- data/test/format_test.rb +5 -1
- data/test/get_worksheet_test.rb +28 -0
- data/test/test_helper.rb +7 -4
- data/test/tmpdir_test.rb +32 -0
- data/test/validations_test.rb +25 -19
- data/test/worksheet_test.rb +10 -2
- metadata +42 -12
- data/libxlsxwriter/cmake/FindMINIZIP.cmake +0 -121
- data/libxlsxwriter/cmake/FindPackage.cmake +0 -183
- data/libxlsxwriter/cmake/i686-toolchain.cmake +0 -7
- data/test/reopen_test.rb +0 -22
data/libxlsxwriter/src/utility.c
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Used in conjunction with the libxlsxwriter library.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
6
|
+
* SPDX-License-Identifier: BSD-2-Clause
|
|
7
|
+
* Copyright 2014-2026, John McNamara, jmcnamara@cpan.org.
|
|
7
8
|
*
|
|
8
9
|
*/
|
|
9
10
|
|
|
@@ -39,6 +40,8 @@ char *error_strings[LXW_MAX_ERRNO + 1] = {
|
|
|
39
40
|
"Feature is not currently supported in this configuration.",
|
|
40
41
|
"NULL function parameter ignored.",
|
|
41
42
|
"Function parameter validation error.",
|
|
43
|
+
"Function string parameter is empty.",
|
|
44
|
+
"Datetime struct parameter has an invalid field value.",
|
|
42
45
|
"Worksheet name exceeds Excel's limit of 31 characters.",
|
|
43
46
|
"Worksheet name cannot contain invalid characters: '[ ] : * ? / \\'",
|
|
44
47
|
"Worksheet name cannot start or end with an apostrophe.",
|
|
@@ -250,18 +253,39 @@ lxw_row_t
|
|
|
250
253
|
lxw_name_to_row(const char *row_str)
|
|
251
254
|
{
|
|
252
255
|
lxw_row_t row_num = 0;
|
|
253
|
-
|
|
256
|
+
|
|
257
|
+
if (!row_str)
|
|
258
|
+
return row_num;
|
|
254
259
|
|
|
255
260
|
/* Skip the column letters and absolute symbol of the A1 cell. */
|
|
256
|
-
while (
|
|
257
|
-
|
|
261
|
+
while (*row_str && !isdigit((unsigned char) *row_str))
|
|
262
|
+
row_str++;
|
|
258
263
|
|
|
259
264
|
/* Convert the row part of the A1 cell to a number. */
|
|
260
|
-
if (
|
|
261
|
-
row_num = atoi(
|
|
265
|
+
if (*row_str)
|
|
266
|
+
row_num = atoi(row_str);
|
|
262
267
|
|
|
263
268
|
if (row_num)
|
|
264
|
-
|
|
269
|
+
row_num--;
|
|
270
|
+
|
|
271
|
+
return row_num;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/*
|
|
275
|
+
* Convert the second row of an Excel range ref to a zero indexed number.
|
|
276
|
+
*/
|
|
277
|
+
uint32_t
|
|
278
|
+
lxw_name_to_row_2(const char *row_str)
|
|
279
|
+
{
|
|
280
|
+
if (!row_str)
|
|
281
|
+
return 0;
|
|
282
|
+
|
|
283
|
+
/* Find the : separator in the range. */
|
|
284
|
+
while (*row_str && *row_str != ':')
|
|
285
|
+
row_str++;
|
|
286
|
+
|
|
287
|
+
if (*row_str)
|
|
288
|
+
return lxw_name_to_row(++row_str);
|
|
265
289
|
else
|
|
266
290
|
return 0;
|
|
267
291
|
}
|
|
@@ -273,52 +297,103 @@ lxw_col_t
|
|
|
273
297
|
lxw_name_to_col(const char *col_str)
|
|
274
298
|
{
|
|
275
299
|
lxw_col_t col_num = 0;
|
|
276
|
-
|
|
300
|
+
|
|
301
|
+
if (!col_str)
|
|
302
|
+
return col_num;
|
|
277
303
|
|
|
278
304
|
/* Convert leading column letters of A1 cell. Ignore absolute $ marker. */
|
|
279
|
-
while (
|
|
280
|
-
if (*
|
|
281
|
-
col_num = (col_num * 26) + (*
|
|
282
|
-
|
|
305
|
+
while (*col_str && (isupper((unsigned char) *col_str) || *col_str == '$')) {
|
|
306
|
+
if (*col_str != '$')
|
|
307
|
+
col_num = (col_num * 26) + (*col_str - 'A' + 1);
|
|
308
|
+
col_str++;
|
|
283
309
|
}
|
|
284
310
|
|
|
285
|
-
|
|
311
|
+
if (col_num)
|
|
312
|
+
col_num--;
|
|
313
|
+
|
|
314
|
+
return col_num;
|
|
286
315
|
}
|
|
287
316
|
|
|
288
317
|
/*
|
|
289
|
-
* Convert the second
|
|
318
|
+
* Convert the second column of an Excel range ref to a zero indexed number.
|
|
290
319
|
*/
|
|
291
|
-
|
|
292
|
-
|
|
320
|
+
uint16_t
|
|
321
|
+
lxw_name_to_col_2(const char *col_str)
|
|
293
322
|
{
|
|
294
|
-
|
|
323
|
+
if (!col_str)
|
|
324
|
+
return 0;
|
|
295
325
|
|
|
296
326
|
/* Find the : separator in the range. */
|
|
297
|
-
while (
|
|
298
|
-
|
|
327
|
+
while (*col_str && *col_str != ':')
|
|
328
|
+
col_str++;
|
|
299
329
|
|
|
300
|
-
if (
|
|
301
|
-
return
|
|
330
|
+
if (*col_str)
|
|
331
|
+
return lxw_name_to_col(++col_str);
|
|
302
332
|
else
|
|
303
|
-
return
|
|
333
|
+
return 0;
|
|
304
334
|
}
|
|
305
335
|
|
|
306
|
-
|
|
307
|
-
*
|
|
308
|
-
*/
|
|
309
|
-
uint16_t
|
|
310
|
-
lxw_name_to_col_2(const char *col_str)
|
|
336
|
+
lxw_error
|
|
337
|
+
lxw_datetime_validate(lxw_datetime *datetime)
|
|
311
338
|
{
|
|
312
|
-
|
|
339
|
+
if (!datetime)
|
|
340
|
+
return LXW_ERROR_DATETIME_VALIDATION;
|
|
313
341
|
|
|
314
|
-
/*
|
|
315
|
-
|
|
316
|
-
|
|
342
|
+
/*
|
|
343
|
+
* Excel uses the year 1900 as the default epoch but it uses 1899-12-31 as
|
|
344
|
+
* the 0 date and internally we use the 0-0-0 date for time only values.
|
|
345
|
+
*/
|
|
346
|
+
if (datetime->year < 1900 &&
|
|
347
|
+
!(datetime->year == 0 &&
|
|
348
|
+
datetime->month == 0 && datetime->day == 0) &&
|
|
349
|
+
!(datetime->year == 1899 &&
|
|
350
|
+
datetime->month == 12 && datetime->day == 31)) {
|
|
317
351
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
return
|
|
352
|
+
LXW_WARN_FORMAT1("lxw_datetime_validate(): invalid year: %d. "
|
|
353
|
+
"Valid range is 1900-9999.", datetime->year);
|
|
354
|
+
|
|
355
|
+
return LXW_ERROR_DATETIME_VALIDATION;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
if (datetime->year > 9999) {
|
|
359
|
+
LXW_WARN_FORMAT1("lxw_datetime_validate(): invalid year: %d. "
|
|
360
|
+
"Valid range is 1900-9999.", datetime->year);
|
|
361
|
+
return LXW_ERROR_DATETIME_VALIDATION;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (datetime->year != 0) {
|
|
365
|
+
if (datetime->month < 1 || datetime->month > 12) {
|
|
366
|
+
LXW_WARN_FORMAT1("lxw_datetime_validate(): invalid month: %d. "
|
|
367
|
+
"Valid range is 1-12.", datetime->month);
|
|
368
|
+
return LXW_ERROR_DATETIME_VALIDATION;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
if (datetime->day < 1 || datetime->day > 31) {
|
|
372
|
+
LXW_WARN_FORMAT1("lxw_datetime_validate(): invalid day: %d. "
|
|
373
|
+
"Valid range is 1-31.", datetime->day);
|
|
374
|
+
return LXW_ERROR_DATETIME_VALIDATION;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (datetime->hour < 0 || datetime->hour > 23) {
|
|
379
|
+
LXW_WARN_FORMAT1("lxw_datetime_validate(): invalid hour: %d. "
|
|
380
|
+
"Valid range is 0-23.", datetime->hour);
|
|
381
|
+
return LXW_ERROR_DATETIME_VALIDATION;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (datetime->min < 0 || datetime->min > 59) {
|
|
385
|
+
LXW_WARN_FORMAT1("lxw_datetime_validate(): invalid minute: %d. "
|
|
386
|
+
"Valid range is 0-59.", datetime->min);
|
|
387
|
+
return LXW_ERROR_DATETIME_VALIDATION;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
if (datetime->sec < 0.0 || datetime->sec >= 60.0) {
|
|
391
|
+
LXW_WARN_FORMAT1("lxw_datetime_validate(): invalid seconds: %.3f. "
|
|
392
|
+
"Valid range is 0.0-59.999.", datetime->sec);
|
|
393
|
+
return LXW_ERROR_DATETIME_VALIDATION;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
return LXW_NO_ERROR;
|
|
322
397
|
}
|
|
323
398
|
|
|
324
399
|
/*
|
|
@@ -326,7 +401,8 @@ lxw_name_to_col_2(const char *col_str)
|
|
|
326
401
|
* or 1904 epoch.
|
|
327
402
|
*/
|
|
328
403
|
double
|
|
329
|
-
|
|
404
|
+
lxw_datetime_to_excel_date_with_epoch(lxw_datetime *datetime,
|
|
405
|
+
uint8_t use_1904_epoch)
|
|
330
406
|
{
|
|
331
407
|
int year = datetime->year;
|
|
332
408
|
int month = datetime->month;
|
|
@@ -335,8 +411,8 @@ lxw_datetime_to_excel_date_epoch(lxw_datetime *datetime, uint8_t date_1904)
|
|
|
335
411
|
int min = datetime->min;
|
|
336
412
|
double sec = datetime->sec;
|
|
337
413
|
double seconds;
|
|
338
|
-
int epoch =
|
|
339
|
-
int offset =
|
|
414
|
+
int epoch = use_1904_epoch ? 1904 : 1900;
|
|
415
|
+
int offset = use_1904_epoch ? 4 : 0;
|
|
340
416
|
int norm = 300;
|
|
341
417
|
int range;
|
|
342
418
|
/* Set month days and check for leap year. */
|
|
@@ -345,9 +421,12 @@ lxw_datetime_to_excel_date_epoch(lxw_datetime *datetime, uint8_t date_1904)
|
|
|
345
421
|
int days = 0;
|
|
346
422
|
int i;
|
|
347
423
|
|
|
424
|
+
if (lxw_datetime_validate(datetime) != LXW_NO_ERROR)
|
|
425
|
+
return 0.0;
|
|
426
|
+
|
|
348
427
|
/* For times without dates set the default date for the epoch. */
|
|
349
428
|
if (!year) {
|
|
350
|
-
if (!
|
|
429
|
+
if (!use_1904_epoch) {
|
|
351
430
|
year = 1899;
|
|
352
431
|
month = 12;
|
|
353
432
|
day = 31;
|
|
@@ -363,7 +442,7 @@ lxw_datetime_to_excel_date_epoch(lxw_datetime *datetime, uint8_t date_1904)
|
|
|
363
442
|
seconds = (hour * 60 * 60 + min * 60 + sec) / (24 * 60 * 60.0);
|
|
364
443
|
|
|
365
444
|
/* Special cases for Excel dates in the 1900 epoch. */
|
|
366
|
-
if (!
|
|
445
|
+
if (!use_1904_epoch) {
|
|
367
446
|
/* Excel 1900 epoch. */
|
|
368
447
|
if (year == 1899 && month == 12 && day == 31)
|
|
369
448
|
return seconds;
|
|
@@ -412,7 +491,7 @@ lxw_datetime_to_excel_date_epoch(lxw_datetime *datetime, uint8_t date_1904)
|
|
|
412
491
|
days -= leap;
|
|
413
492
|
|
|
414
493
|
/* Adjust for Excel erroneously treating 1900 as a leap year. */
|
|
415
|
-
if (!
|
|
494
|
+
if (!use_1904_epoch && days > 59)
|
|
416
495
|
days++;
|
|
417
496
|
|
|
418
497
|
return days + seconds;
|
|
@@ -424,7 +503,7 @@ lxw_datetime_to_excel_date_epoch(lxw_datetime *datetime, uint8_t date_1904)
|
|
|
424
503
|
double
|
|
425
504
|
lxw_datetime_to_excel_datetime(lxw_datetime *datetime)
|
|
426
505
|
{
|
|
427
|
-
return
|
|
506
|
+
return lxw_datetime_to_excel_date_with_epoch(datetime, LXW_FALSE);
|
|
428
507
|
}
|
|
429
508
|
|
|
430
509
|
/*
|
|
@@ -434,7 +513,7 @@ lxw_datetime_to_excel_datetime(lxw_datetime *datetime)
|
|
|
434
513
|
double
|
|
435
514
|
lxw_unixtime_to_excel_date(int64_t unixtime)
|
|
436
515
|
{
|
|
437
|
-
return
|
|
516
|
+
return lxw_unixtime_to_excel_date_with_epoch(unixtime, LXW_FALSE);
|
|
438
517
|
}
|
|
439
518
|
|
|
440
519
|
/*
|
|
@@ -442,14 +521,15 @@ lxw_unixtime_to_excel_date(int64_t unixtime)
|
|
|
442
521
|
* 1900 or 1904 epoch.
|
|
443
522
|
*/
|
|
444
523
|
double
|
|
445
|
-
|
|
524
|
+
lxw_unixtime_to_excel_date_with_epoch(int64_t unixtime,
|
|
525
|
+
uint8_t use_1904_epoch)
|
|
446
526
|
{
|
|
447
527
|
double excel_datetime = 0.0;
|
|
448
|
-
double epoch =
|
|
528
|
+
double epoch = use_1904_epoch ? 24107.0 : 25568.0;
|
|
449
529
|
|
|
450
530
|
excel_datetime = epoch + (unixtime / (24 * 60 * 60.0));
|
|
451
531
|
|
|
452
|
-
if (!
|
|
532
|
+
if (!use_1904_epoch && excel_datetime >= 60.0)
|
|
453
533
|
excel_datetime = excel_datetime + 1.0;
|
|
454
534
|
|
|
455
535
|
return excel_datetime;
|
|
@@ -514,6 +594,16 @@ lxw_str_tolower(char *str)
|
|
|
514
594
|
str[i] = tolower(str[i]);
|
|
515
595
|
}
|
|
516
596
|
|
|
597
|
+
/* Simple check for empty strings. */
|
|
598
|
+
uint8_t
|
|
599
|
+
lxw_str_is_empty(const char *str)
|
|
600
|
+
{
|
|
601
|
+
if (str[0] == '\0')
|
|
602
|
+
return 1;
|
|
603
|
+
else
|
|
604
|
+
return 0;
|
|
605
|
+
}
|
|
606
|
+
|
|
517
607
|
/* Create a quoted version of the worksheet name, or return an unmodified
|
|
518
608
|
* copy if it doesn't required quoting. */
|
|
519
609
|
char *
|
data/libxlsxwriter/src/vml.c
CHANGED