xlsxwriter 0.2.0 → 0.2.1.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -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))