xlsxwriter 0.2.0 → 0.2.1.pre

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.
@@ -40,13 +40,13 @@ LXW_RB_GENERATE_CHARTSHEET_NAMES(lxw_chartsheet_names, lxw_chartsheet_name,
40
40
  STATIC int
41
41
  _worksheet_name_cmp(lxw_worksheet_name *name1, lxw_worksheet_name *name2)
42
42
  {
43
- return strcmp(name1->name, name2->name);
43
+ return lxw_strcasecmp(name1->name, name2->name);
44
44
  }
45
45
 
46
46
  STATIC int
47
47
  _chartsheet_name_cmp(lxw_chartsheet_name *name1, lxw_chartsheet_name *name2)
48
48
  {
49
- return strcmp(name1->name, name2->name);
49
+ return lxw_strcasecmp(name1->name, name2->name);
50
50
  }
51
51
 
52
52
  /*
@@ -208,6 +208,8 @@ lxw_workbook_free(lxw_workbook *workbook)
208
208
  lxw_sst_free(workbook->sst);
209
209
  free(workbook->options.tmpdir);
210
210
  free(workbook->ordered_charts);
211
+ free(workbook->vba_project);
212
+ free(workbook->vba_codename);
211
213
  free(workbook);
212
214
  }
213
215
 
@@ -885,9 +887,9 @@ _prepare_drawings(lxw_workbook *self)
885
887
  lxw_sheet *sheet;
886
888
  lxw_worksheet *worksheet;
887
889
  lxw_image_options *image_options;
888
- uint16_t chart_ref_id = 0;
889
- uint16_t image_ref_id = 0;
890
- uint16_t drawing_id = 0;
890
+ uint32_t chart_ref_id = 0;
891
+ uint32_t image_ref_id = 0;
892
+ uint32_t drawing_id = 0;
891
893
  uint8_t is_chartsheet;
892
894
 
893
895
  STAILQ_FOREACH(sheet, self->sheets, list_pointers) {
@@ -1135,6 +1137,10 @@ _write_file_version(lxw_workbook *self)
1135
1137
  LXW_PUSH_ATTRIBUTES_STR("lowestEdited", "4");
1136
1138
  LXW_PUSH_ATTRIBUTES_STR("rupBuild", "4505");
1137
1139
 
1140
+ if (self->vba_project)
1141
+ LXW_PUSH_ATTRIBUTES_STR("codeName",
1142
+ "{37E998C4-C9E5-D4B9-71C8-EB1FF731991C}");
1143
+
1138
1144
  lxw_xml_empty_tag(self->file, "fileVersion", &attributes);
1139
1145
 
1140
1146
  LXW_FREE_ATTRIBUTES();
@@ -1150,6 +1156,10 @@ _write_workbook_pr(lxw_workbook *self)
1150
1156
  struct xml_attribute *attribute;
1151
1157
 
1152
1158
  LXW_INIT_ATTRIBUTES();
1159
+
1160
+ if (self->vba_codename)
1161
+ LXW_PUSH_ATTRIBUTES_STR("codeName", self->vba_codename);
1162
+
1153
1163
  LXW_PUSH_ATTRIBUTES_STR("defaultThemeVersion", "124226");
1154
1164
 
1155
1165
  lxw_xml_empty_tag(self->file, "workbookPr", &attributes);
@@ -1470,6 +1480,7 @@ workbook_new_opt(const char *filename, lxw_workbook_options *options)
1470
1480
  if (options) {
1471
1481
  workbook->options.constant_memory = options->constant_memory;
1472
1482
  workbook->options.tmpdir = lxw_strdup(options->tmpdir);
1483
+ workbook->options.use_zip64 = options->use_zip64;
1473
1484
  }
1474
1485
 
1475
1486
  return workbook;
@@ -1717,6 +1728,22 @@ workbook_close(lxw_workbook *self)
1717
1728
  worksheet->active = 1;
1718
1729
  }
1719
1730
 
1731
+ /* Set workbook and worksheet VBA codenames if a macro has been added. */
1732
+ if (self->vba_project) {
1733
+ if (!self->vba_codename)
1734
+ workbook_set_vba_name(self, "ThisWorkbook");
1735
+
1736
+ STAILQ_FOREACH(sheet, self->sheets, list_pointers) {
1737
+ if (sheet->is_chartsheet)
1738
+ continue;
1739
+ else
1740
+ worksheet = sheet->u.worksheet;
1741
+
1742
+ if (!worksheet->vba_codename)
1743
+ worksheet_set_vba_name(worksheet, worksheet->name);
1744
+ }
1745
+ }
1746
+
1720
1747
  /* Set the defined names for the worksheets such as Print Titles. */
1721
1748
  _prepare_defined_names(self);
1722
1749
 
@@ -1727,13 +1754,15 @@ workbook_close(lxw_workbook *self)
1727
1754
  _add_chart_cache_data(self);
1728
1755
 
1729
1756
  /* Create a packager object to assemble sub-elements into a zip file. */
1730
- packager = lxw_packager_new(self->filename, self->options.tmpdir);
1757
+ packager = lxw_packager_new(self->filename,
1758
+ self->options.tmpdir,
1759
+ self->options.use_zip64);
1731
1760
 
1732
1761
  /* If the packager fails it is generally due to a zip permission error. */
1733
1762
  if (packager == NULL) {
1734
1763
  fprintf(stderr, "[ERROR] workbook_close(): "
1735
1764
  "Error creating '%s'. "
1736
- "Error = %s\n", self->filename, strerror(errno));
1765
+ "System error = %s\n", self->filename, strerror(errno));
1737
1766
 
1738
1767
  error = LXW_ERROR_CREATING_XLSX_FILE;
1739
1768
  goto mem_error;
@@ -1749,26 +1778,47 @@ workbook_close(lxw_workbook *self)
1749
1778
  if (error == LXW_ERROR_CREATING_TMPFILE) {
1750
1779
  fprintf(stderr, "[ERROR] workbook_close(): "
1751
1780
  "Error creating tmpfile(s) to assemble '%s'. "
1752
- "Error = %s\n", self->filename, strerror(errno));
1781
+ "System error = %s\n", self->filename, strerror(errno));
1753
1782
  }
1754
1783
 
1755
- /* If LXW_ERROR_ZIP_FILE_OPERATION then errno is set by zlib. */
1784
+ /* If LXW_ERROR_ZIP_FILE_OPERATION then errno is set by zip. */
1756
1785
  if (error == LXW_ERROR_ZIP_FILE_OPERATION) {
1757
1786
  fprintf(stderr, "[ERROR] workbook_close(): "
1758
- "Zlib error while creating xlsx file '%s'. "
1759
- "Error = %s\n", self->filename, strerror(errno));
1787
+ "Zip ZIP_ERRNO error while creating xlsx file '%s'. "
1788
+ "System error = %s\n", self->filename, strerror(errno));
1789
+ }
1790
+
1791
+ /* If LXW_ERROR_ZIP_PARAMETER_ERROR then errno is set by zip. */
1792
+ if (error == LXW_ERROR_ZIP_PARAMETER_ERROR) {
1793
+ fprintf(stderr, "[ERROR] workbook_close(): "
1794
+ "Zip ZIP_PARAMERROR error while creating xlsx file '%s'. "
1795
+ "System error = %s\n", self->filename, strerror(errno));
1796
+ }
1797
+
1798
+ /* If LXW_ERROR_ZIP_BAD_ZIP_FILE then errno is set by zip. */
1799
+ if (error == LXW_ERROR_ZIP_BAD_ZIP_FILE) {
1800
+ fprintf(stderr, "[ERROR] workbook_close(): "
1801
+ "Zip ZIP_BADZIPFILE error while creating xlsx file '%s'. "
1802
+ "This may require the use_zip64 option for large files. "
1803
+ "System error = %s\n", self->filename, strerror(errno));
1804
+ }
1805
+
1806
+ /* If LXW_ERROR_ZIP_INTERNAL_ERROR then errno is set by zip. */
1807
+ if (error == LXW_ERROR_ZIP_INTERNAL_ERROR) {
1808
+ fprintf(stderr, "[ERROR] workbook_close(): "
1809
+ "Zip ZIP_INTERNALERROR error while creating xlsx file '%s'. "
1810
+ "System error = %s\n", self->filename, strerror(errno));
1760
1811
  }
1761
1812
 
1762
1813
  /* The next 2 error conditions don't set errno. */
1763
1814
  if (error == LXW_ERROR_ZIP_FILE_ADD) {
1764
1815
  fprintf(stderr, "[ERROR] workbook_close(): "
1765
- "Zlib error adding file to xlsx file '%s'.\n",
1766
- self->filename);
1816
+ "Zip error adding file to xlsx file '%s'.\n", self->filename);
1767
1817
  }
1768
1818
 
1769
1819
  if (error == LXW_ERROR_ZIP_CLOSE) {
1770
1820
  fprintf(stderr, "[ERROR] workbook_close(): "
1771
- "Zlib error closing xlsx file '%s'.\n", self->filename);
1821
+ "Zip error closing xlsx file '%s'.\n", self->filename);
1772
1822
  }
1773
1823
 
1774
1824
  mem_error:
@@ -2114,6 +2164,14 @@ workbook_validate_sheet_name(lxw_workbook *self, const char *sheetname)
2114
2164
  if (strpbrk(sheetname, "[]:*?/\\"))
2115
2165
  return LXW_ERROR_INVALID_SHEETNAME_CHARACTER;
2116
2166
 
2167
+ /* Check that the worksheet doesn't start or end with an apostrophe. */
2168
+ if (sheetname[0] == '\'' || sheetname[strlen(sheetname) - 1] == '\'')
2169
+ return LXW_ERROR_SHEETNAME_START_END_APOSTROPHE;
2170
+
2171
+ /* Check that the worksheet name isn't the reserved work "History". */
2172
+ if (lxw_strcasecmp(sheetname, "history") == 0)
2173
+ return LXW_ERROR_SHEETNAME_RESERVED;
2174
+
2117
2175
  /* Check if the worksheet name is already in use. */
2118
2176
  if (workbook_get_worksheet_by_name(self, sheetname))
2119
2177
  return LXW_ERROR_SHEETNAME_ALREADY_USED;
@@ -2124,3 +2182,48 @@ workbook_validate_sheet_name(lxw_workbook *self, const char *sheetname)
2124
2182
 
2125
2183
  return LXW_NO_ERROR;
2126
2184
  }
2185
+
2186
+ /*
2187
+ * Add a vbaProject binary to the Excel workbook.
2188
+ */
2189
+ lxw_error
2190
+ workbook_add_vba_project(lxw_workbook *self, const char *filename)
2191
+ {
2192
+ FILE *filehandle;
2193
+
2194
+ if (!filename) {
2195
+ LXW_WARN("workbook_add_vba_project(): "
2196
+ "filename must be specified.");
2197
+ return LXW_ERROR_NULL_PARAMETER_IGNORED;
2198
+ }
2199
+
2200
+ /* Check that the vbaProject file exists and can be opened. */
2201
+ filehandle = fopen(filename, "rb");
2202
+ if (!filehandle) {
2203
+ LXW_WARN_FORMAT1("workbook_add_vba_project(): "
2204
+ "file doesn't exist or can't be opened: %s.",
2205
+ filename);
2206
+ return LXW_ERROR_PARAMETER_VALIDATION;
2207
+ }
2208
+ fclose(filehandle);
2209
+
2210
+ self->vba_project = lxw_strdup(filename);
2211
+
2212
+ return LXW_NO_ERROR;
2213
+ }
2214
+
2215
+ /*
2216
+ * Set the VBA name for the workbook.
2217
+ */
2218
+ lxw_error
2219
+ workbook_set_vba_name(lxw_workbook *self, const char *name)
2220
+ {
2221
+ if (!name) {
2222
+ LXW_WARN("workbook_set_vba_name(): " "name must be specified.");
2223
+ return LXW_ERROR_NULL_PARAMETER_IGNORED;
2224
+ }
2225
+
2226
+ self->vba_codename = lxw_strdup(name);
2227
+
2228
+ return LXW_NO_ERROR;
2229
+ }
@@ -448,6 +448,7 @@ lxw_worksheet_free(lxw_worksheet *worksheet)
448
448
  free(worksheet->vbreaks);
449
449
  free(worksheet->name);
450
450
  free(worksheet->quoted_name);
451
+ free(worksheet->vba_codename);
451
452
 
452
453
  free(worksheet);
453
454
  worksheet = NULL;
@@ -1507,7 +1508,8 @@ _worksheet_write_optimized_sheet_data(lxw_worksheet *self)
1507
1508
  while (read_size) {
1508
1509
  read_size =
1509
1510
  fread(buffer, 1, LXW_BUFFER_SIZE, self->optimize_tmpfile);
1510
- fwrite(buffer, 1, read_size, self->file);
1511
+ /* Ignore return value. There is no easy way to raise error. */
1512
+ (void) fwrite(buffer, 1, read_size, self->file);
1511
1513
  }
1512
1514
 
1513
1515
  fclose(self->optimize_tmpfile);
@@ -1992,7 +1994,7 @@ _worksheet_position_object_emus(lxw_worksheet *self,
1992
1994
  */
1993
1995
  void
1994
1996
  lxw_worksheet_prepare_image(lxw_worksheet *self,
1995
- uint16_t image_ref_id, uint16_t drawing_id,
1997
+ uint32_t image_ref_id, uint32_t drawing_id,
1996
1998
  lxw_image_options *image_data)
1997
1999
  {
1998
2000
  lxw_drawing_object *drawing_object;
@@ -2079,8 +2081,8 @@ mem_error:
2079
2081
  */
2080
2082
  void
2081
2083
  lxw_worksheet_prepare_chart(lxw_worksheet *self,
2082
- uint16_t chart_ref_id,
2083
- uint16_t drawing_id,
2084
+ uint32_t chart_ref_id,
2085
+ uint32_t drawing_id,
2084
2086
  lxw_image_options *image_data,
2085
2087
  uint8_t is_chartsheet)
2086
2088
  {
@@ -3147,7 +3149,7 @@ _worksheet_write_sheet_pr(lxw_worksheet *self)
3147
3149
  LXW_INIT_ATTRIBUTES();
3148
3150
 
3149
3151
  if (self->vba_codename)
3150
- LXW_PUSH_ATTRIBUTES_INT("codeName", self->vba_codename);
3152
+ LXW_PUSH_ATTRIBUTES_STR("codeName", self->vba_codename);
3151
3153
 
3152
3154
  if (self->filter_on)
3153
3155
  LXW_PUSH_ATTRIBUTES_STR("filterMode", "1");
@@ -5629,7 +5631,14 @@ worksheet_insert_image_buffer_opt(lxw_worksheet *self,
5629
5631
  /* Write the image buffer to a temporary file so we can read the
5630
5632
  * dimensions like an ordinary file. */
5631
5633
  image_stream = lxw_tmpfile(self->tmpdir);
5632
- fwrite(image_buffer, 1, image_size, image_stream);
5634
+ if (!image_stream)
5635
+ return LXW_ERROR_CREATING_TMPFILE;
5636
+
5637
+ if (fwrite(image_buffer, 1, image_size, image_stream) != image_size) {
5638
+ fclose(image_stream);
5639
+ return LXW_ERROR_CREATING_TMPFILE;
5640
+ }
5641
+
5633
5642
  rewind(image_stream);
5634
5643
 
5635
5644
  /* Create a new object to hold the image options. */
@@ -6066,3 +6075,19 @@ worksheet_data_validation_cell(lxw_worksheet *self, lxw_row_t row,
6066
6075
  return worksheet_data_validation_range(self, row, col,
6067
6076
  row, col, validation);
6068
6077
  }
6078
+
6079
+ /*
6080
+ * Set the VBA name for the worksheet.
6081
+ */
6082
+ lxw_error
6083
+ worksheet_set_vba_name(lxw_worksheet *self, const char *name)
6084
+ {
6085
+ if (!name) {
6086
+ LXW_WARN("worksheet_set_vba_name(): " "name must be specified.");
6087
+ return LXW_ERROR_NULL_PARAMETER_IGNORED;
6088
+ }
6089
+
6090
+ self->vba_codename = lxw_strdup(name);
6091
+
6092
+ return LXW_NO_ERROR;
6093
+ }
@@ -31,15 +31,18 @@ workbook_alloc(VALUE klass) {
31
31
  }
32
32
 
33
33
  /* call-seq:
34
- * XlsxWriter::Workbook.new(path, constant_memory: false, tmpdir: nil) -> workbook
35
- * XlsxWriter::Workbook.new(path, constant_memory: false, tmpdir: nil) { |wb| block } -> nil
36
- * XlsxWriter::Workbook.open(path, constant_memory: false, tmpdir: nil) { |wb| block } -> nil
34
+ * XlsxWriter::Workbook.new(path, constant_memory: false, tmpdir: nil, use_zip64: false) -> workbook
35
+ * XlsxWriter::Workbook.new(path, constant_memory: false, tmpdir: nil, use_zip64: false) { |wb| block } -> nil
36
+ * XlsxWriter::Workbook.open(path, constant_memory: false, tmpdir: nil, use_zip64: false) { |wb| block } -> nil
37
37
  *
38
38
  * Creates a new Xlsx workbook in file +path+ and returns a new Workbook object.
39
39
  *
40
40
  * If +constant_memory+ is set to true workbook data is stored in temporary files
41
41
  * in +tmpdir+, considerably reducing memory consumption for large documents.
42
42
  *
43
+ * If +use_zip64+ is set to truthy value zip64 extensions are enabled for the resulting xlsx file. It allows
44
+ * for files in the archive to have size >4GB.
45
+ *
43
46
  * XlsxWriter::Workbook.open('/tmp/test.xlsx', constant_memory: true) do |wb|
44
47
  * # ... populate the workbook with data ...
45
48
  * end
@@ -61,7 +64,8 @@ workbook_init(int argc, VALUE *argv, VALUE self) {
61
64
  struct workbook *ptr;
62
65
  lxw_workbook_options options = {
63
66
  .constant_memory = 0,
64
- .tmpdir = NULL
67
+ .tmpdir = NULL,
68
+ .use_zip64 = 0
65
69
  };
66
70
 
67
71
  if (argc < 1 || argc > 2) {
@@ -75,6 +79,10 @@ workbook_init(int argc, VALUE *argv, VALUE self) {
75
79
  if (!NIL_P(tmpdir))
76
80
  options.tmpdir = RSTRING_PTR(tmpdir);
77
81
  }
82
+ VALUE use_zip64_ = rb_hash_aref(argv[1], ID2SYM(rb_intern("use_zip64")));
83
+ if (!NIL_P(use_zip64_) && use_zip64_) {
84
+ options.use_zip64 = 1;
85
+ }
78
86
  }
79
87
 
80
88
  Data_Get_Struct(self, struct workbook, ptr);
@@ -274,6 +282,24 @@ workbook_add_chart_(VALUE self, VALUE type) {
274
282
  return chart;
275
283
  }
276
284
 
285
+ /* call-seq:
286
+ * wb.add_vba_project(filename)
287
+ *
288
+ * Adds a vba project to the workbook (has to be extracted from a xlsm file).
289
+ * Only one file per workbook is allowed. Documents with vba projects should have
290
+ * extension "xlsm" rather than "xlsx" to avoid reader/editor software warnings.
291
+ */
292
+ VALUE
293
+ workbook_add_vba_project_(VALUE self, VALUE filename) {
294
+ struct workbook *ptr;
295
+ Data_Get_Struct(self, struct workbook, ptr);
296
+
297
+ lxw_error err = workbook_add_vba_project(ptr->workbook, StringValueCStr(filename));
298
+ handle_lxw_error(err);
299
+
300
+ return self;
301
+ }
302
+
277
303
  /* :nodoc: */
278
304
  VALUE
279
305
  workbook_set_default_xf_indices_(VALUE self) {
@@ -283,6 +309,22 @@ workbook_set_default_xf_indices_(VALUE self) {
283
309
  return self;
284
310
  }
285
311
 
312
+ /* call-seq:
313
+ * wb.vba_name = name
314
+ *
315
+ * Set the VBA name for the workbook.
316
+ */
317
+ VALUE
318
+ workbook_set_vba_name_(VALUE self, VALUE name) {
319
+ struct workbook *ptr;
320
+ Data_Get_Struct(self, struct workbook, ptr);
321
+
322
+ lxw_error err = workbook_set_vba_name(ptr->workbook, StringValueCStr(name));
323
+ handle_lxw_error(err);
324
+
325
+ return name;
326
+ }
327
+
286
328
  /* call-seq: wb.properties -> wb_properties
287
329
  *
288
330
  * Returns worbook properties accessor object.
@@ -382,14 +424,16 @@ init_xlsxwriter_workbook() {
382
424
  rb_define_alias(rb_singleton_class(cWorkbook), "open", "new");
383
425
  rb_define_method(cWorkbook, "initialize", workbook_init, -1);
384
426
  rb_define_method(cWorkbook, "close", workbook_release, 0);
385
- rb_define_method(cWorkbook, "add_worksheet", workbook_add_worksheet_, -1);
386
- rb_define_method(cWorkbook, "add_format", workbook_add_format_, 2);
387
427
  rb_define_method(cWorkbook, "add_chart", workbook_add_chart_, 1);
388
- rb_define_method(cWorkbook, "set_default_xf_indices", workbook_set_default_xf_indices_, 0);
389
- rb_define_method(cWorkbook, "properties", workbook_properties_, 0);
428
+ rb_define_method(cWorkbook, "add_format", workbook_add_format_, 2);
429
+ rb_define_method(cWorkbook, "add_vba_project", workbook_add_vba_project_, 1);
430
+ rb_define_method(cWorkbook, "add_worksheet", workbook_add_worksheet_, -1);
390
431
  rb_define_method(cWorkbook, "define_name", workbook_define_name_, 2);
432
+ rb_define_method(cWorkbook, "properties", workbook_properties_, 0);
433
+ rb_define_method(cWorkbook, "set_default_xf_indices", workbook_set_default_xf_indices_, 0);
391
434
  rb_define_method(cWorkbook, "validate_sheet_name", workbook_validate_sheet_name_, 1);
392
435
  rb_define_method(cWorkbook, "validate_worksheet_name", workbook_validate_sheet_name_, 1);
436
+ rb_define_method(cWorkbook, "vba_name=", workbook_set_vba_name_, 1);
393
437
 
394
438
  /*
395
439
  * This attribute contains effective font widths used for automatic column
@@ -624,6 +624,53 @@ worksheet_insert_image_(int argc, VALUE *argv, VALUE self) {
624
624
  return self;
625
625
  }
626
626
 
627
+ /* call-seq:
628
+ * ws.insert_image_buffer(cell, data, options) -> self
629
+ * ws.insert_image_buffer(row, col, data, options) -> self
630
+ *
631
+ * Adds data validation or limits user input to a list of values.
632
+ */
633
+ VALUE
634
+ worksheet_insert_image_buffer_(int argc, VALUE *argv, VALUE self) {
635
+ lxw_row_t row;
636
+ lxw_col_t col;
637
+ VALUE data = Qnil;
638
+ VALUE opts = Qnil;
639
+ lxw_image_options options;
640
+ char with_options = '\0';
641
+
642
+ rb_check_arity(argc, 2, 4);
643
+ int larg = extract_cell(argc, argv, &row, &col);
644
+
645
+ if (larg < argc) {
646
+ data = argv[larg];
647
+ ++larg;
648
+ } else {
649
+ rb_raise(rb_eArgError, "Cannot embed image without data");
650
+ }
651
+
652
+ if (larg < argc) {
653
+ opts = argv[larg];
654
+ ++larg;
655
+ }
656
+ struct worksheet *ptr;
657
+ Data_Get_Struct(self, struct worksheet, ptr);
658
+
659
+ if (!NIL_P(opts)) {
660
+ options = val_to_lxw_image_options(opts, &with_options);
661
+ }
662
+
663
+ lxw_error error;
664
+ if (with_options) {
665
+ error = worksheet_insert_image_buffer_opt(ptr->worksheet, row, col, (const unsigned char *) RSTRING_PTR(data), RSTRING_LEN(data), &options);
666
+ } else {
667
+ error = worksheet_insert_image_buffer(ptr->worksheet, row, col, (const unsigned char *) RSTRING_PTR(data), RSTRING_LEN(data));
668
+ }
669
+ handle_lxw_error(error);
670
+
671
+ return self;
672
+ }
673
+
627
674
  /* call-seq:
628
675
  * ws.insert_chart(cell, chart, opts = {}) -> self
629
676
  * ws.insert_chart(row, col, chart, opts = {}) -> self
@@ -1485,6 +1532,23 @@ worksheet_data_validation_(int argc, VALUE *argv, VALUE self) {
1485
1532
  return self;
1486
1533
  }
1487
1534
 
1535
+ /* call-seq: wb.vba_name = name
1536
+ *
1537
+ * Set the VBA name for the worksheet.
1538
+ */
1539
+ VALUE
1540
+ worksheet_set_vba_name_(VALUE self, VALUE name) {
1541
+ struct worksheet *ptr;
1542
+ Data_Get_Struct(self, struct worksheet, ptr);
1543
+
1544
+ lxw_error err = worksheet_set_vba_name(ptr->worksheet, StringValueCStr(name));
1545
+ handle_lxw_error(err);
1546
+
1547
+ return name;
1548
+ }
1549
+
1550
+ // Helpers
1551
+
1488
1552
  lxw_col_t
1489
1553
  value_to_col(VALUE value) {
1490
1554
  switch (TYPE(value)) {
@@ -1600,6 +1664,7 @@ val_to_lxw_image_options(VALUE opts, char *with_options) {
1600
1664
  SET_IMG_OPT("scale", options.x_scale = options.y_scale = NUM2DBL(val));
1601
1665
  SET_IMG_OPT("x_scale", options.x_scale = NUM2DBL(val));
1602
1666
  SET_IMG_OPT("y_scale", options.y_scale = NUM2DBL(val));
1667
+ SET_IMG_OPT("description", options.description = StringValueCStr(val));
1603
1668
  return options;
1604
1669
  }
1605
1670
  #undef SET_IMG_OPT
@@ -1626,6 +1691,7 @@ init_xlsxwriter_worksheet() {
1626
1691
  rb_define_method(cWorksheet, "set_row", worksheet_set_row_, 2);
1627
1692
  rb_define_method(cWorksheet, "set_column", worksheet_set_column_, 3);
1628
1693
  rb_define_method(cWorksheet, "insert_image", worksheet_insert_image_, -1);
1694
+ rb_define_method(cWorksheet, "insert_image_buffer", worksheet_insert_image_buffer_, -1);
1629
1695
  rb_define_method(cWorksheet, "insert_chart", worksheet_insert_chart_, -1);
1630
1696
  rb_define_method(cWorksheet, "merge_range", worksheet_merge_range_, -1);
1631
1697
  rb_define_method(cWorksheet, "autofilter", worksheet_autofilter_, -1);
@@ -1668,6 +1734,8 @@ init_xlsxwriter_worksheet() {
1668
1734
  rb_define_method(cWorksheet, "vertical_dpi=", worksheet_set_vertical_dpi_, 1);
1669
1735
 
1670
1736
  rb_define_method(cWorksheet, "add_data_validation", worksheet_data_validation_, -1);
1737
+ rb_define_method(cWorksheet, "vba_name=", worksheet_set_vba_name_, 1);
1738
+
1671
1739
  rb_define_private_method(cWorksheet, "extract_column", rb_extract_col, 1);
1672
1740
 
1673
1741
  #define MAP_LXW_WH_CONST(name, val_name) rb_define_const(cWorksheet, #name, INT2NUM(LXW_##val_name))