fast_excel 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +1 -7
  3. data/CHANGELOG.md +9 -0
  4. data/Gemfile +1 -1
  5. data/examples/example.rb +2 -0
  6. data/examples/example_date_time.rb +38 -0
  7. data/fast_excel.gemspec +2 -2
  8. data/lib/fast_excel/binding/format.rb +17 -0
  9. data/lib/fast_excel/binding/workbook.rb +39 -17
  10. data/lib/fast_excel/binding/worksheet.rb +57 -13
  11. data/lib/fast_excel/binding.rb +7 -7
  12. data/lib/fast_excel.rb +27 -20
  13. data/libxlsxwriter/.github/FUNDING.yml +1 -0
  14. data/libxlsxwriter/.github/ISSUE_TEMPLATE.md +85 -0
  15. data/libxlsxwriter/.github/PULL_REQUEST_TEMPLATE.md +130 -0
  16. data/libxlsxwriter/.github/workflows/cmake_actions.yml +48 -0
  17. data/libxlsxwriter/.github/workflows/code_style.yml +23 -0
  18. data/libxlsxwriter/.github/workflows/coverity.yml +22 -0
  19. data/libxlsxwriter/.github/workflows/make_actions.yml +52 -0
  20. data/libxlsxwriter/.github/workflows/valgrind.yml +23 -0
  21. data/libxlsxwriter/.github/workflows/windows_build.yml +54 -0
  22. data/libxlsxwriter/.github/workflows/zig_build.yml +22 -0
  23. data/libxlsxwriter/.gitignore +16 -1
  24. data/libxlsxwriter/.indent.pro +24 -0
  25. data/libxlsxwriter/CMakeLists.txt +156 -56
  26. data/libxlsxwriter/CONTRIBUTING.md +2 -2
  27. data/libxlsxwriter/Changes.txt +344 -2
  28. data/libxlsxwriter/LICENSE.txt +66 -8
  29. data/libxlsxwriter/Makefile +151 -54
  30. data/libxlsxwriter/Package.swift +42 -0
  31. data/libxlsxwriter/Readme.md +4 -2
  32. data/libxlsxwriter/build.zig +324 -0
  33. data/libxlsxwriter/build.zig.zon +11 -0
  34. data/libxlsxwriter/cmake/FindMINIZIP.cmake +3 -3
  35. data/libxlsxwriter/cocoapods/libxlsxwriter-umbrella.h +6 -0
  36. data/libxlsxwriter/include/xlsxwriter/app.h +2 -1
  37. data/libxlsxwriter/include/xlsxwriter/chart.h +236 -32
  38. data/libxlsxwriter/include/xlsxwriter/chartsheet.h +7 -7
  39. data/libxlsxwriter/include/xlsxwriter/comment.h +76 -0
  40. data/libxlsxwriter/include/xlsxwriter/common.h +111 -50
  41. data/libxlsxwriter/include/xlsxwriter/content_types.h +8 -1
  42. data/libxlsxwriter/include/xlsxwriter/core.h +1 -1
  43. data/libxlsxwriter/include/xlsxwriter/custom.h +1 -1
  44. data/libxlsxwriter/include/xlsxwriter/drawing.h +11 -20
  45. data/libxlsxwriter/include/xlsxwriter/format.h +121 -8
  46. data/libxlsxwriter/include/xlsxwriter/hash_table.h +1 -1
  47. data/libxlsxwriter/include/xlsxwriter/metadata.h +49 -0
  48. data/libxlsxwriter/include/xlsxwriter/packager.h +27 -16
  49. data/libxlsxwriter/include/xlsxwriter/relationships.h +1 -1
  50. data/libxlsxwriter/include/xlsxwriter/shared_strings.h +1 -1
  51. data/libxlsxwriter/include/xlsxwriter/styles.h +13 -7
  52. data/libxlsxwriter/include/xlsxwriter/table.h +51 -0
  53. data/libxlsxwriter/include/xlsxwriter/theme.h +1 -1
  54. data/libxlsxwriter/include/xlsxwriter/third_party/emyg_dtoa.h +26 -0
  55. data/libxlsxwriter/include/xlsxwriter/third_party/ioapi.h +27 -25
  56. data/libxlsxwriter/include/xlsxwriter/third_party/md5.h +45 -0
  57. data/libxlsxwriter/include/xlsxwriter/third_party/zip.h +155 -153
  58. data/libxlsxwriter/include/xlsxwriter/utility.h +70 -8
  59. data/libxlsxwriter/include/xlsxwriter/vml.h +55 -0
  60. data/libxlsxwriter/include/xlsxwriter/workbook.h +218 -47
  61. data/libxlsxwriter/include/xlsxwriter/worksheet.h +2770 -241
  62. data/libxlsxwriter/include/xlsxwriter/xmlwriter.h +12 -8
  63. data/libxlsxwriter/include/xlsxwriter.h +4 -2
  64. data/libxlsxwriter/libxlsxwriter.podspec +8 -5
  65. data/libxlsxwriter/src/Makefile +58 -21
  66. data/libxlsxwriter/src/app.c +5 -2
  67. data/libxlsxwriter/src/chart.c +396 -81
  68. data/libxlsxwriter/src/chartsheet.c +22 -22
  69. data/libxlsxwriter/src/comment.c +443 -0
  70. data/libxlsxwriter/src/content_types.c +40 -1
  71. data/libxlsxwriter/src/core.c +2 -2
  72. data/libxlsxwriter/src/custom.c +1 -1
  73. data/libxlsxwriter/src/drawing.c +160 -40
  74. data/libxlsxwriter/src/format.c +109 -25
  75. data/libxlsxwriter/src/hash_table.c +1 -1
  76. data/libxlsxwriter/src/metadata.c +283 -0
  77. data/libxlsxwriter/src/packager.c +794 -94
  78. data/libxlsxwriter/src/relationships.c +1 -1
  79. data/libxlsxwriter/src/shared_strings.c +2 -4
  80. data/libxlsxwriter/src/styles.c +353 -58
  81. data/libxlsxwriter/src/table.c +304 -0
  82. data/libxlsxwriter/src/theme.c +1 -1
  83. data/libxlsxwriter/src/utility.c +143 -43
  84. data/libxlsxwriter/src/vml.c +1062 -0
  85. data/libxlsxwriter/src/workbook.c +567 -77
  86. data/libxlsxwriter/src/worksheet.c +6668 -1462
  87. data/libxlsxwriter/src/xmlwriter.c +95 -5
  88. data/libxlsxwriter/third_party/dtoa/Makefile +42 -0
  89. data/libxlsxwriter/third_party/dtoa/emyg_dtoa.c +461 -0
  90. data/libxlsxwriter/third_party/dtoa/emyg_dtoa.h +26 -0
  91. data/libxlsxwriter/third_party/md5/Makefile +42 -0
  92. data/libxlsxwriter/third_party/md5/md5.c +291 -0
  93. data/libxlsxwriter/third_party/md5/md5.h +45 -0
  94. data/libxlsxwriter/third_party/minizip/Makefile +3 -8
  95. data/libxlsxwriter/third_party/minizip/Makefile.orig +8 -4
  96. data/libxlsxwriter/third_party/minizip/MiniZip64_Changes.txt +1 -1
  97. data/libxlsxwriter/third_party/minizip/configure.ac +1 -1
  98. data/libxlsxwriter/third_party/minizip/crypt.h +13 -16
  99. data/libxlsxwriter/third_party/minizip/ioapi.c +31 -57
  100. data/libxlsxwriter/third_party/minizip/ioapi.h +31 -23
  101. data/libxlsxwriter/third_party/minizip/iowin32.c +29 -45
  102. data/libxlsxwriter/third_party/minizip/iowin32.h +4 -4
  103. data/libxlsxwriter/third_party/minizip/miniunz.c +29 -56
  104. data/libxlsxwriter/third_party/minizip/minizip.c +38 -49
  105. data/libxlsxwriter/third_party/minizip/mztools.c +1 -7
  106. data/libxlsxwriter/third_party/minizip/unzip.c +202 -342
  107. data/libxlsxwriter/third_party/minizip/unzip.h +74 -74
  108. data/libxlsxwriter/third_party/minizip/zip.c +165 -218
  109. data/libxlsxwriter/third_party/minizip/zip.h +164 -154
  110. data/libxlsxwriter/third_party/tmpfileplus/Makefile +3 -3
  111. data/libxlsxwriter/version.txt +1 -1
  112. data/test/auto_width_test.rb +20 -0
  113. data/test/default_format_test.rb +1 -1
  114. data/test/validations_test.rb +3 -3
  115. data/test/worksheet_test.rb +6 -1
  116. metadata +33 -7
  117. data/libxlsxwriter/.travis.yml +0 -37
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2019, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2022, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -14,7 +14,7 @@
14
14
  /*
15
15
  * Forward declarations.
16
16
  */
17
- STATIC void _write_font(lxw_styles *self, lxw_format *format,
17
+ STATIC void _write_font(lxw_styles *self, lxw_format *format, uint8_t is_dxf,
18
18
  uint8_t is_rich_string);
19
19
 
20
20
  /*****************************************************************************
@@ -34,9 +34,12 @@ lxw_styles_new(void)
34
34
 
35
35
  styles->xf_formats = calloc(1, sizeof(struct lxw_formats));
36
36
  GOTO_LABEL_ON_MEM_ERROR(styles->xf_formats, mem_error);
37
-
38
37
  STAILQ_INIT(styles->xf_formats);
39
38
 
39
+ styles->dxf_formats = calloc(1, sizeof(struct lxw_formats));
40
+ GOTO_LABEL_ON_MEM_ERROR(styles->dxf_formats, mem_error);
41
+ STAILQ_INIT(styles->dxf_formats);
42
+
40
43
  return styles;
41
44
 
42
45
  mem_error:
@@ -55,7 +58,7 @@ lxw_styles_free(lxw_styles *styles)
55
58
  if (!styles)
56
59
  return;
57
60
 
58
- /* Free the formats in the styles. */
61
+ /* Free the xf formats in the styles. */
59
62
  if (styles->xf_formats) {
60
63
  while (!STAILQ_EMPTY(styles->xf_formats)) {
61
64
  format = STAILQ_FIRST(styles->xf_formats);
@@ -65,6 +68,16 @@ lxw_styles_free(lxw_styles *styles)
65
68
  free(styles->xf_formats);
66
69
  }
67
70
 
71
+ /* Free the dxf formats in the styles. */
72
+ if (styles->dxf_formats) {
73
+ while (!STAILQ_EMPTY(styles->dxf_formats)) {
74
+ format = STAILQ_FIRST(styles->dxf_formats);
75
+ STAILQ_REMOVE_HEAD(styles->dxf_formats, list_pointers);
76
+ free(format);
77
+ }
78
+ free(styles->dxf_formats);
79
+ }
80
+
68
81
  free(styles);
69
82
  }
70
83
 
@@ -72,7 +85,7 @@ lxw_styles_free(lxw_styles *styles)
72
85
  * Write the <t> element for rich strings.
73
86
  */
74
87
  void
75
- lxw_styles_write_string_fragment(lxw_styles *self, char *string)
88
+ lxw_styles_write_string_fragment(lxw_styles *self, const char *string)
76
89
  {
77
90
  struct xml_attribute_list attributes;
78
91
  struct xml_attribute *attribute;
@@ -93,7 +106,7 @@ void
93
106
  lxw_styles_write_rich_font(lxw_styles *self, lxw_format *format)
94
107
  {
95
108
 
96
- _write_font(self, format, LXW_TRUE);
109
+ _write_font(self, format, LXW_FALSE, LXW_TRUE);
97
110
  }
98
111
 
99
112
  /*****************************************************************************
@@ -136,10 +149,68 @@ _write_num_fmt(lxw_styles *self, uint16_t num_fmt_id, char *format_code)
136
149
  {
137
150
  struct xml_attribute_list attributes;
138
151
  struct xml_attribute *attribute;
152
+ char *format_codes[] = {
153
+ "General",
154
+ "0",
155
+ "0.00",
156
+ "#,##0",
157
+ "#,##0.00",
158
+ "($#,##0_);($#,##0)",
159
+ "($#,##0_);[Red]($#,##0)",
160
+ "($#,##0.00_);($#,##0.00)",
161
+ "($#,##0.00_);[Red]($#,##0.00)",
162
+ "0%",
163
+ "0.00%",
164
+ "0.00E+00",
165
+ "# ?/?",
166
+ "# ?" "?/?" "?", /* Split string to avoid unintentional trigraph. */
167
+ "m/d/yy",
168
+ "d-mmm-yy",
169
+ "d-mmm",
170
+ "mmm-yy",
171
+ "h:mm AM/PM",
172
+ "h:mm:ss AM/PM",
173
+ "h:mm",
174
+ "h:mm:ss",
175
+ "m/d/yy h:mm",
176
+ "General",
177
+ "General",
178
+ "General",
179
+ "General",
180
+ "General",
181
+ "General",
182
+ "General",
183
+ "General",
184
+ "General",
185
+ "General",
186
+ "General",
187
+ "General",
188
+ "General",
189
+ "General",
190
+ "(#,##0_);(#,##0)",
191
+ "(#,##0_);[Red](#,##0)",
192
+ "(#,##0.00_);(#,##0.00)",
193
+ "(#,##0.00_);[Red](#,##0.00)",
194
+ "_(* #,##0_);_(* (#,##0);_(* \"-\"_);_(@_)",
195
+ "_($* #,##0_);_($* (#,##0);_($* \"-\"_);_(@_)",
196
+ "_(* #,##0.00_);_(* (#,##0.00);_(* \"-\"??_);_(@_)",
197
+ "_($* #,##0.00_);_($* (#,##0.00);_($* \"-\"??_);_(@_)",
198
+ "mm:ss",
199
+ "[h]:mm:ss",
200
+ "mm:ss.0",
201
+ "##0.0E+0",
202
+ "@"
203
+ };
139
204
 
140
205
  LXW_INIT_ATTRIBUTES();
141
206
  LXW_PUSH_ATTRIBUTES_INT("numFmtId", num_fmt_id);
142
- LXW_PUSH_ATTRIBUTES_STR("formatCode", format_code);
207
+
208
+ if (num_fmt_id < 50)
209
+ LXW_PUSH_ATTRIBUTES_STR("formatCode", format_codes[num_fmt_id]);
210
+ else if (num_fmt_id < 164)
211
+ LXW_PUSH_ATTRIBUTES_STR("formatCode", "General");
212
+ else
213
+ LXW_PUSH_ATTRIBUTES_STR("formatCode", format_code);
143
214
 
144
215
  lxw_xml_empty_tag(self->file, "numFmt", &attributes);
145
216
 
@@ -240,6 +311,23 @@ _write_font_color_rgb(lxw_styles *self, int32_t rgb)
240
311
  LXW_FREE_ATTRIBUTES();
241
312
  }
242
313
 
314
+ /*
315
+ * Write the <color> element for indexed colors.
316
+ */
317
+ STATIC void
318
+ _write_font_color_indexed(lxw_styles *self, uint8_t index)
319
+ {
320
+ struct xml_attribute_list attributes;
321
+ struct xml_attribute *attribute;
322
+
323
+ LXW_INIT_ATTRIBUTES();
324
+ LXW_PUSH_ATTRIBUTES_INT("indexed", index);
325
+
326
+ lxw_xml_empty_tag(self->file, "color", &attributes);
327
+
328
+ LXW_FREE_ATTRIBUTES();
329
+ }
330
+
243
331
  /*
244
332
  * Write the <name> element.
245
333
  */
@@ -329,11 +417,45 @@ _write_font_underline(lxw_styles *self, uint8_t underline)
329
417
 
330
418
  }
331
419
 
420
+ /*
421
+ * Write the font <condense> element.
422
+ */
423
+ STATIC void
424
+ _write_font_condense(lxw_styles *self)
425
+ {
426
+ struct xml_attribute_list attributes;
427
+ struct xml_attribute *attribute;
428
+
429
+ LXW_INIT_ATTRIBUTES();
430
+ LXW_PUSH_ATTRIBUTES_STR("val", "0");
431
+
432
+ lxw_xml_empty_tag(self->file, "condense", &attributes);
433
+
434
+ LXW_FREE_ATTRIBUTES();
435
+ }
436
+
437
+ /*
438
+ * Write the font <extend> element.
439
+ */
440
+ STATIC void
441
+ _write_font_extend(lxw_styles *self)
442
+ {
443
+ struct xml_attribute_list attributes;
444
+ struct xml_attribute *attribute;
445
+
446
+ LXW_INIT_ATTRIBUTES();
447
+ LXW_PUSH_ATTRIBUTES_STR("val", "0");
448
+
449
+ lxw_xml_empty_tag(self->file, "extend", &attributes);
450
+
451
+ LXW_FREE_ATTRIBUTES();
452
+ }
453
+
332
454
  /*
333
455
  * Write the <vertAlign> font sub-element.
334
456
  */
335
457
  STATIC void
336
- _write_vert_align(lxw_styles *self, const char *align)
458
+ _write_font_vert_align(lxw_styles *self, const char *align)
337
459
  {
338
460
  struct xml_attribute_list attributes;
339
461
  struct xml_attribute *attribute;
@@ -350,13 +472,20 @@ _write_vert_align(lxw_styles *self, const char *align)
350
472
  * Write the <font> element.
351
473
  */
352
474
  STATIC void
353
- _write_font(lxw_styles *self, lxw_format *format, uint8_t is_rich_string)
475
+ _write_font(lxw_styles *self, lxw_format *format, uint8_t is_dxf,
476
+ uint8_t is_rich_string)
354
477
  {
355
478
  if (is_rich_string)
356
479
  lxw_xml_start_tag(self->file, "rPr", NULL);
357
480
  else
358
481
  lxw_xml_start_tag(self->file, "font", NULL);
359
482
 
483
+ if (format->font_condense)
484
+ _write_font_condense(self);
485
+
486
+ if (format->font_extend)
487
+ _write_font_extend(self);
488
+
360
489
  if (format->bold)
361
490
  lxw_xml_empty_tag(self->file, "b", NULL);
362
491
 
@@ -376,30 +505,41 @@ _write_font(lxw_styles *self, lxw_format *format, uint8_t is_rich_string)
376
505
  _write_font_underline(self, format->underline);
377
506
 
378
507
  if (format->font_script == LXW_FONT_SUPERSCRIPT)
379
- _write_vert_align(self, "superscript");
508
+ _write_font_vert_align(self, "superscript");
380
509
 
381
510
  if (format->font_script == LXW_FONT_SUBSCRIPT)
382
- _write_vert_align(self, "subscript");
511
+ _write_font_vert_align(self, "subscript");
383
512
 
384
- if (format->font_size > 0.0)
513
+ if (!is_dxf && format->font_size > 0.0)
385
514
  _write_font_size(self, format->font_size);
386
515
 
387
516
  if (format->theme)
388
517
  _write_font_color_theme(self, format->theme);
518
+ else if (format->color_indexed)
519
+ _write_font_color_indexed(self, format->color_indexed);
389
520
  else if (format->font_color != LXW_COLOR_UNSET)
390
521
  _write_font_color_rgb(self, format->font_color);
391
- else
522
+ else if (!is_dxf)
392
523
  _write_font_color_theme(self, LXW_DEFAULT_FONT_THEME);
393
524
 
394
- _write_font_name(self, format->font_name, is_rich_string);
395
- _write_font_family(self, format->font_family);
525
+ if (!is_dxf) {
526
+ _write_font_name(self, format->font_name, is_rich_string);
527
+ _write_font_family(self, format->font_family);
396
528
 
397
- /* Only write the scheme element for the default font type if it
398
- * is a hyperlink. */
399
- if ((!*format->font_name
400
- || strcmp(LXW_DEFAULT_FONT_NAME, format->font_name) == 0)
401
- && !format->hyperlink) {
402
- _write_font_scheme(self, format->font_scheme);
529
+ /* Only write the scheme element for the default font type if it
530
+ * is a hyperlink. */
531
+ if ((!*format->font_name
532
+ || strcmp(LXW_DEFAULT_FONT_NAME, format->font_name) == 0)
533
+ && !format->hyperlink) {
534
+ _write_font_scheme(self, format->font_scheme);
535
+ }
536
+ }
537
+
538
+ if (format->hyperlink) {
539
+ self->has_hyperlink = LXW_TRUE;
540
+
541
+ if (self->hyperlink_font_id == 0)
542
+ self->hyperlink_font_id = format->font_index;
403
543
  }
404
544
 
405
545
  if (is_rich_string)
@@ -408,6 +548,22 @@ _write_font(lxw_styles *self, lxw_format *format, uint8_t is_rich_string)
408
548
  lxw_xml_end_tag(self->file, "font");
409
549
  }
410
550
 
551
+ /*
552
+ * Write the <font> element for comments.
553
+ */
554
+ STATIC void
555
+ _write_comment_font(lxw_styles *self)
556
+ {
557
+ lxw_xml_start_tag(self->file, "font", NULL);
558
+
559
+ _write_font_size(self, 8);
560
+ _write_font_color_indexed(self, 81);
561
+ _write_font_name(self, "Tahoma", LXW_FALSE);
562
+ _write_font_family(self, 2);
563
+
564
+ lxw_xml_end_tag(self->file, "font");
565
+ }
566
+
411
567
  /*
412
568
  * Write the <fonts> element.
413
569
  */
@@ -417,17 +573,26 @@ _write_fonts(lxw_styles *self)
417
573
  struct xml_attribute_list attributes;
418
574
  struct xml_attribute *attribute;
419
575
  lxw_format *format;
576
+ uint32_t count;
420
577
 
421
578
  LXW_INIT_ATTRIBUTES();
422
- LXW_PUSH_ATTRIBUTES_INT("count", self->font_count);
579
+
580
+ count = self->font_count;
581
+ if (self->has_comments)
582
+ count++;
583
+
584
+ LXW_PUSH_ATTRIBUTES_INT("count", count);
423
585
 
424
586
  lxw_xml_start_tag(self->file, "fonts", &attributes);
425
587
 
426
588
  STAILQ_FOREACH(format, self->xf_formats, list_pointers) {
427
589
  if (format->has_font)
428
- _write_font(self, format, LXW_FALSE);
590
+ _write_font(self, format, LXW_FALSE, LXW_FALSE);
429
591
  }
430
592
 
593
+ if (self->has_comments)
594
+ _write_comment_font(self);
595
+
431
596
  lxw_xml_end_tag(self->file, "fonts");
432
597
 
433
598
  LXW_FREE_ATTRIBUTES();
@@ -476,7 +641,7 @@ _write_fg_color(lxw_styles *self, lxw_color_t color)
476
641
  * Write the <bgColor> element.
477
642
  */
478
643
  STATIC void
479
- _write_bg_color(lxw_styles *self, lxw_color_t color)
644
+ _write_bg_color(lxw_styles *self, lxw_color_t color, uint8_t pattern)
480
645
  {
481
646
  struct xml_attribute_list attributes;
482
647
  struct xml_attribute *attribute;
@@ -485,15 +650,17 @@ _write_bg_color(lxw_styles *self, lxw_color_t color)
485
650
  LXW_INIT_ATTRIBUTES();
486
651
 
487
652
  if (color == LXW_COLOR_UNSET) {
488
- LXW_PUSH_ATTRIBUTES_STR("indexed", "64");
653
+ if (pattern <= LXW_PATTERN_SOLID) {
654
+ LXW_PUSH_ATTRIBUTES_STR("indexed", "64");
655
+ lxw_xml_empty_tag(self->file, "bgColor", &attributes);
656
+ }
489
657
  }
490
658
  else {
491
659
  lxw_snprintf(rgb_str, LXW_ATTR_32, "FF%06X", color & LXW_COLOR_MASK);
492
660
  LXW_PUSH_ATTRIBUTES_STR("rgb", rgb_str);
661
+ lxw_xml_empty_tag(self->file, "bgColor", &attributes);
493
662
  }
494
663
 
495
- lxw_xml_empty_tag(self->file, "bgColor", &attributes);
496
-
497
664
  LXW_FREE_ATTRIBUTES();
498
665
  }
499
666
 
@@ -501,7 +668,7 @@ _write_bg_color(lxw_styles *self, lxw_color_t color)
501
668
  * Write the <fill> element.
502
669
  */
503
670
  STATIC void
504
- _write_fill(lxw_styles *self, lxw_format *format)
671
+ _write_fill(lxw_styles *self, lxw_format *format, uint8_t is_dxf)
505
672
  {
506
673
  struct xml_attribute_list attributes;
507
674
  struct xml_attribute *attribute;
@@ -532,11 +699,24 @@ _write_fill(lxw_styles *self, lxw_format *format)
532
699
  "gray0625",
533
700
  };
534
701
 
702
+ if (is_dxf) {
703
+ bg_color = format->dxf_bg_color;
704
+ fg_color = format->dxf_fg_color;
705
+ }
706
+
535
707
  LXW_INIT_ATTRIBUTES();
536
708
 
709
+ /* Special handling for pattern only case. */
710
+ if (!bg_color && !fg_color && pattern) {
711
+ _write_default_fill(self, patterns[pattern]);
712
+ LXW_FREE_ATTRIBUTES();
713
+ return;
714
+ }
715
+
537
716
  lxw_xml_start_tag(self->file, "fill", NULL);
538
717
 
539
- if (pattern)
718
+ /* None/Solid patterns are handled differently for dxf formats. */
719
+ if (pattern && !(is_dxf && pattern <= LXW_PATTERN_SOLID))
540
720
  LXW_PUSH_ATTRIBUTES_STR("patternType", patterns[pattern]);
541
721
 
542
722
  lxw_xml_start_tag(self->file, "patternFill", &attributes);
@@ -544,7 +724,7 @@ _write_fill(lxw_styles *self, lxw_format *format)
544
724
  if (fg_color != LXW_COLOR_UNSET)
545
725
  _write_fg_color(self, fg_color);
546
726
 
547
- _write_bg_color(self, bg_color);
727
+ _write_bg_color(self, bg_color, pattern);
548
728
 
549
729
  lxw_xml_end_tag(self->file, "patternFill");
550
730
  lxw_xml_end_tag(self->file, "fill");
@@ -573,7 +753,7 @@ _write_fills(lxw_styles *self)
573
753
 
574
754
  STAILQ_FOREACH(format, self->xf_formats, list_pointers) {
575
755
  if (format->has_fill)
576
- _write_fill(self, format);
756
+ _write_fill(self, format, LXW_FALSE);
577
757
  }
578
758
 
579
759
  lxw_xml_end_tag(self->file, "fills");
@@ -654,7 +834,7 @@ _write_sub_border(lxw_styles *self, const char *type, uint8_t style,
654
834
  * Write the <border> element.
655
835
  */
656
836
  STATIC void
657
- _write_border(lxw_styles *self, lxw_format *format)
837
+ _write_border(lxw_styles *self, lxw_format *format, uint8_t is_dxf)
658
838
  {
659
839
  struct xml_attribute_list attributes;
660
840
  struct xml_attribute *attribute;
@@ -675,7 +855,7 @@ _write_border(lxw_styles *self, lxw_format *format)
675
855
 
676
856
  /* Ensure that a default diag border is set if the diag type is set. */
677
857
  if (format->diag_type && !format->diag_border) {
678
- format->diag_border = 1;
858
+ format->diag_border = LXW_BORDER_THIN;
679
859
  }
680
860
 
681
861
  /* Write the start border tag. */
@@ -686,8 +866,16 @@ _write_border(lxw_styles *self, lxw_format *format)
686
866
  _write_sub_border(self, "right", format->right, format->right_color);
687
867
  _write_sub_border(self, "top", format->top, format->top_color);
688
868
  _write_sub_border(self, "bottom", format->bottom, format->bottom_color);
689
- _write_sub_border(self,
690
- "diagonal", format->diag_border, format->diag_color);
869
+
870
+ if (is_dxf) {
871
+ _write_sub_border(self, "vertical", 0, LXW_COLOR_UNSET);
872
+ _write_sub_border(self, "horizontal", 0, LXW_COLOR_UNSET);
873
+ }
874
+
875
+ /* Conditional DXF formats don't allow diagonal borders. */
876
+ if (!is_dxf)
877
+ _write_sub_border(self, "diagonal",
878
+ format->diag_border, format->diag_color);
691
879
 
692
880
  lxw_xml_end_tag(self->file, "border");
693
881
 
@@ -711,7 +899,7 @@ _write_borders(lxw_styles *self)
711
899
 
712
900
  STAILQ_FOREACH(format, self->xf_formats, list_pointers) {
713
901
  if (format->has_border)
714
- _write_border(self, format);
902
+ _write_border(self, format, LXW_FALSE);
715
903
  }
716
904
 
717
905
  lxw_xml_end_tag(self->file, "borders");
@@ -719,22 +907,70 @@ _write_borders(lxw_styles *self)
719
907
  LXW_FREE_ATTRIBUTES();
720
908
  }
721
909
 
910
+ /*
911
+ * Write the <alignment> element for hyperlinks.
912
+ */
913
+ STATIC void
914
+ _write_hyperlink_alignment(lxw_styles *self)
915
+ {
916
+ struct xml_attribute_list attributes;
917
+ struct xml_attribute *attribute;
918
+
919
+ LXW_INIT_ATTRIBUTES();
920
+ LXW_PUSH_ATTRIBUTES_STR("vertical", "top");
921
+
922
+ lxw_xml_empty_tag(self->file, "alignment", &attributes);
923
+
924
+ LXW_FREE_ATTRIBUTES();
925
+ }
926
+
927
+ /*
928
+ * Write the <protection> element for hyperlinks.
929
+ */
930
+ STATIC void
931
+ _write_hyperlink_protection(lxw_styles *self)
932
+ {
933
+ struct xml_attribute_list attributes;
934
+ struct xml_attribute *attribute;
935
+
936
+ LXW_INIT_ATTRIBUTES();
937
+ LXW_PUSH_ATTRIBUTES_STR("locked", "0");
938
+
939
+ lxw_xml_empty_tag(self->file, "protection", &attributes);
940
+
941
+ LXW_FREE_ATTRIBUTES();
942
+ }
943
+
722
944
  /*
723
945
  * Write the <xf> element for styles.
724
946
  */
725
947
  STATIC void
726
- _write_style_xf(lxw_styles *self)
948
+ _write_style_xf(lxw_styles *self, uint8_t has_hyperlink, uint16_t font_id)
727
949
  {
728
950
  struct xml_attribute_list attributes;
729
951
  struct xml_attribute *attribute;
730
952
 
731
953
  LXW_INIT_ATTRIBUTES();
732
954
  LXW_PUSH_ATTRIBUTES_STR("numFmtId", "0");
733
- LXW_PUSH_ATTRIBUTES_STR("fontId", "0");
955
+ LXW_PUSH_ATTRIBUTES_INT("fontId", font_id);
734
956
  LXW_PUSH_ATTRIBUTES_STR("fillId", "0");
735
957
  LXW_PUSH_ATTRIBUTES_STR("borderId", "0");
736
958
 
737
- lxw_xml_empty_tag(self->file, "xf", &attributes);
959
+ if (has_hyperlink) {
960
+ LXW_PUSH_ATTRIBUTES_STR("applyNumberFormat", "0");
961
+ LXW_PUSH_ATTRIBUTES_STR("applyFill", "0");
962
+ LXW_PUSH_ATTRIBUTES_STR("applyBorder", "0");
963
+ LXW_PUSH_ATTRIBUTES_STR("applyAlignment", "0");
964
+ LXW_PUSH_ATTRIBUTES_STR("applyProtection", "0");
965
+
966
+ lxw_xml_start_tag(self->file, "xf", &attributes);
967
+ _write_hyperlink_alignment(self);
968
+ _write_hyperlink_protection(self);
969
+ lxw_xml_end_tag(self->file, "xf");
970
+ }
971
+ else {
972
+ lxw_xml_empty_tag(self->file, "xf", &attributes);
973
+ }
738
974
 
739
975
  LXW_FREE_ATTRIBUTES();
740
976
  }
@@ -749,10 +985,18 @@ _write_cell_style_xfs(lxw_styles *self)
749
985
  struct xml_attribute *attribute;
750
986
 
751
987
  LXW_INIT_ATTRIBUTES();
752
- LXW_PUSH_ATTRIBUTES_STR("count", "1");
988
+
989
+ if (self->has_hyperlink)
990
+ LXW_PUSH_ATTRIBUTES_STR("count", "2");
991
+ else
992
+ LXW_PUSH_ATTRIBUTES_STR("count", "1");
753
993
 
754
994
  lxw_xml_start_tag(self->file, "cellStyleXfs", &attributes);
755
- _write_style_xf(self);
995
+ _write_style_xf(self, LXW_FALSE, 0);
996
+
997
+ if (self->has_hyperlink)
998
+ _write_style_xf(self, self->has_hyperlink, self->hyperlink_font_id);
999
+
756
1000
  lxw_xml_end_tag(self->file, "cellStyleXfs");
757
1001
 
758
1002
  LXW_FREE_ATTRIBUTES();
@@ -936,13 +1180,16 @@ _write_xf(lxw_styles *self, lxw_format *format)
936
1180
  LXW_PUSH_ATTRIBUTES_INT("fontId", format->font_index);
937
1181
  LXW_PUSH_ATTRIBUTES_INT("fillId", format->fill_index);
938
1182
  LXW_PUSH_ATTRIBUTES_INT("borderId", format->border_index);
939
- LXW_PUSH_ATTRIBUTES_STR("xfId", "0");
1183
+ LXW_PUSH_ATTRIBUTES_INT("xfId", format->xf_id);
1184
+
1185
+ if (format->quote_prefix)
1186
+ LXW_PUSH_ATTRIBUTES_STR("quotePrefix", "1");
940
1187
 
941
1188
  if (format->num_format_index > 0)
942
1189
  LXW_PUSH_ATTRIBUTES_STR("applyNumberFormat", "1");
943
1190
 
944
1191
  /* Add applyFont attribute if XF format uses a font element. */
945
- if (format->font_index > 0)
1192
+ if (format->font_index > 0 && !format->hyperlink)
946
1193
  LXW_PUSH_ATTRIBUTES_STR("applyFont", "1");
947
1194
 
948
1195
  /* Add applyFill attribute if XF format uses a fill element. */
@@ -954,10 +1201,10 @@ _write_xf(lxw_styles *self, lxw_format *format)
954
1201
  LXW_PUSH_ATTRIBUTES_STR("applyBorder", "1");
955
1202
 
956
1203
  /* We can also have applyAlignment without a sub-element. */
957
- if (apply_alignment)
1204
+ if (apply_alignment || format->hyperlink)
958
1205
  LXW_PUSH_ATTRIBUTES_STR("applyAlignment", "1");
959
1206
 
960
- if (has_protection)
1207
+ if (has_protection || format->hyperlink)
961
1208
  LXW_PUSH_ATTRIBUTES_STR("applyProtection", "1");
962
1209
 
963
1210
  /* Write XF with sub-elements if required. */
@@ -988,14 +1235,27 @@ _write_cell_xfs(lxw_styles *self)
988
1235
  struct xml_attribute_list attributes;
989
1236
  struct xml_attribute *attribute;
990
1237
  lxw_format *format;
1238
+ uint32_t count = self->xf_count;
1239
+ uint32_t i = 0;
1240
+
1241
+ /* If the last format is "font_only" it is for the comment font and
1242
+ * shouldn't be counted. This is a workaround to get the last object
1243
+ * in the list since STAILQ_LAST() requires __containerof and isn't
1244
+ * ANSI compatible. */
1245
+ STAILQ_FOREACH(format, self->xf_formats, list_pointers) {
1246
+ i++;
1247
+ if (i == self->xf_count && format->font_only)
1248
+ count--;
1249
+ }
991
1250
 
992
1251
  LXW_INIT_ATTRIBUTES();
993
- LXW_PUSH_ATTRIBUTES_INT("count", self->xf_count);
1252
+ LXW_PUSH_ATTRIBUTES_INT("count", count);
994
1253
 
995
1254
  lxw_xml_start_tag(self->file, "cellXfs", &attributes);
996
1255
 
997
1256
  STAILQ_FOREACH(format, self->xf_formats, list_pointers) {
998
- _write_xf(self, format);
1257
+ if (!format->font_only)
1258
+ _write_xf(self, format);
999
1259
  }
1000
1260
 
1001
1261
  lxw_xml_end_tag(self->file, "cellXfs");
@@ -1007,15 +1267,16 @@ _write_cell_xfs(lxw_styles *self)
1007
1267
  * Write the <cellStyle> element.
1008
1268
  */
1009
1269
  STATIC void
1010
- _write_cell_style(lxw_styles *self)
1270
+ _write_cell_style(lxw_styles *self, char *name, uint8_t xf_id,
1271
+ uint8_t builtin_id)
1011
1272
  {
1012
1273
  struct xml_attribute_list attributes;
1013
1274
  struct xml_attribute *attribute;
1014
1275
 
1015
1276
  LXW_INIT_ATTRIBUTES();
1016
- LXW_PUSH_ATTRIBUTES_STR("name", "Normal");
1017
- LXW_PUSH_ATTRIBUTES_STR("xfId", "0");
1018
- LXW_PUSH_ATTRIBUTES_STR("builtinId", "0");
1277
+ LXW_PUSH_ATTRIBUTES_STR("name", name);
1278
+ LXW_PUSH_ATTRIBUTES_INT("xfId", xf_id);
1279
+ LXW_PUSH_ATTRIBUTES_INT("builtinId", builtin_id);
1019
1280
 
1020
1281
  lxw_xml_empty_tag(self->file, "cellStyle", &attributes);
1021
1282
 
@@ -1031,10 +1292,19 @@ _write_cell_styles(lxw_styles *self)
1031
1292
  struct xml_attribute_list attributes;
1032
1293
  struct xml_attribute *attribute;
1033
1294
  LXW_INIT_ATTRIBUTES();
1034
- LXW_PUSH_ATTRIBUTES_STR("count", "1");
1295
+
1296
+ if (self->has_hyperlink)
1297
+ LXW_PUSH_ATTRIBUTES_STR("count", "2");
1298
+ else
1299
+ LXW_PUSH_ATTRIBUTES_STR("count", "1");
1035
1300
 
1036
1301
  lxw_xml_start_tag(self->file, "cellStyles", &attributes);
1037
- _write_cell_style(self);
1302
+
1303
+ if (self->has_hyperlink)
1304
+ _write_cell_style(self, "Hyperlink", 1, 8);
1305
+
1306
+ _write_cell_style(self, "Normal", 0, 0);
1307
+
1038
1308
  lxw_xml_end_tag(self->file, "cellStyles");
1039
1309
 
1040
1310
  LXW_FREE_ATTRIBUTES();
@@ -1042,18 +1312,46 @@ _write_cell_styles(lxw_styles *self)
1042
1312
 
1043
1313
  /*
1044
1314
  * Write the <dxfs> element.
1315
+ *
1045
1316
  */
1046
1317
  STATIC void
1047
1318
  _write_dxfs(lxw_styles *self)
1048
1319
  {
1049
1320
  struct xml_attribute_list attributes;
1050
1321
  struct xml_attribute *attribute;
1322
+ lxw_format *format;
1323
+ uint32_t count = self->dxf_count;
1051
1324
 
1052
1325
  LXW_INIT_ATTRIBUTES();
1053
- LXW_PUSH_ATTRIBUTES_STR("count", "0");
1326
+ LXW_PUSH_ATTRIBUTES_INT("count", count);
1327
+
1328
+ if (count) {
1329
+ lxw_xml_start_tag(self->file, "dxfs", &attributes);
1330
+
1331
+ STAILQ_FOREACH(format, self->dxf_formats, list_pointers) {
1332
+ lxw_xml_start_tag(self->file, "dxf", NULL);
1333
+
1334
+ if (format->has_dxf_font)
1335
+ _write_font(self, format, LXW_TRUE, LXW_FALSE);
1054
1336
 
1055
- lxw_xml_empty_tag(self->file, "dxfs", &attributes);
1337
+ if (format->num_format_index)
1338
+ _write_num_fmt(self, format->num_format_index,
1339
+ format->num_format);
1056
1340
 
1341
+ if (format->has_dxf_fill)
1342
+ _write_fill(self, format, LXW_TRUE);
1343
+
1344
+ if (format->has_dxf_border)
1345
+ _write_border(self, format, LXW_TRUE);
1346
+
1347
+ lxw_xml_end_tag(self->file, "dxf");
1348
+ }
1349
+
1350
+ lxw_xml_end_tag(self->file, "dxfs");
1351
+ }
1352
+ else {
1353
+ lxw_xml_empty_tag(self->file, "dxfs", &attributes);
1354
+ }
1057
1355
  LXW_FREE_ATTRIBUTES();
1058
1356
  }
1059
1357
 
@@ -1121,9 +1419,6 @@ lxw_styles_assemble_xml_file(lxw_styles *self)
1121
1419
  /* Write the tableStyles element. */
1122
1420
  _write_table_styles(self);
1123
1421
 
1124
- /* Write the colors element. */
1125
- /* _write_colors(self); */
1126
-
1127
1422
  /* Close the style sheet tag. */
1128
1423
  lxw_xml_end_tag(self->file, "styleSheet");
1129
1424
  }