fast_excel 0.2.2 → 0.4.0

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 (100) hide show
  1. checksums.yaml +5 -5
  2. data/.dockerignore +2 -0
  3. data/.gitignore +7 -0
  4. data/.travis.yml +32 -9
  5. data/CHANGELOG.md +36 -1
  6. data/Dockerfile.test +17 -0
  7. data/Gemfile +2 -1
  8. data/Gemfile.lock +33 -24
  9. data/LICENSE +21 -0
  10. data/Makefile +13 -0
  11. data/README.md +177 -40
  12. data/Rakefile +11 -1
  13. data/benchmarks/1k_rows.rb +17 -4
  14. data/benchmarks/20k_rows.rb +4 -0
  15. data/benchmarks/auto_width.rb +37 -0
  16. data/benchmarks/init.rb +14 -2
  17. data/benchmarks/memory.rb +8 -0
  18. data/benchmarks/profiler.rb +27 -0
  19. data/benchmarks/write_value.rb +62 -0
  20. data/examples/example.rb +3 -3
  21. data/examples/example_auto_width.rb +26 -0
  22. data/examples/example_filters.rb +36 -0
  23. data/examples/example_formula.rb +1 -3
  24. data/examples/example_hyperlink.rb +20 -0
  25. data/ext/fast_excel/extconf.rb +3 -0
  26. data/ext/fast_excel/text_width_ext.c +460 -0
  27. data/fast_excel.gemspec +3 -4
  28. data/letters.html +114 -0
  29. data/lib/fast_excel.rb +131 -25
  30. data/lib/fast_excel/binding.rb +33 -21
  31. data/lib/fast_excel/binding/chart.rb +20 -1
  32. data/lib/fast_excel/binding/format.rb +11 -4
  33. data/lib/fast_excel/binding/workbook.rb +10 -2
  34. data/lib/fast_excel/binding/worksheet.rb +44 -27
  35. data/libxlsxwriter/.gitignore +1 -0
  36. data/libxlsxwriter/.indent.pro +8 -0
  37. data/libxlsxwriter/.travis.yml +12 -0
  38. data/libxlsxwriter/CMakeLists.txt +338 -0
  39. data/libxlsxwriter/CONTRIBUTING.md +1 -1
  40. data/libxlsxwriter/Changes.txt +162 -0
  41. data/libxlsxwriter/LICENSE.txt +65 -4
  42. data/libxlsxwriter/Makefile +33 -11
  43. data/libxlsxwriter/Readme.md +3 -1
  44. data/libxlsxwriter/cocoapods/libxlsxwriter-umbrella.h +2 -1
  45. data/libxlsxwriter/cocoapods/libxlsxwriter.modulemap +2 -2
  46. data/libxlsxwriter/include/xlsxwriter.h +2 -2
  47. data/libxlsxwriter/include/xlsxwriter/app.h +2 -2
  48. data/libxlsxwriter/include/xlsxwriter/chart.h +164 -13
  49. data/libxlsxwriter/include/xlsxwriter/chartsheet.h +544 -0
  50. data/libxlsxwriter/include/xlsxwriter/common.h +35 -6
  51. data/libxlsxwriter/include/xlsxwriter/content_types.h +5 -2
  52. data/libxlsxwriter/include/xlsxwriter/core.h +2 -2
  53. data/libxlsxwriter/include/xlsxwriter/custom.h +2 -2
  54. data/libxlsxwriter/include/xlsxwriter/drawing.h +3 -2
  55. data/libxlsxwriter/include/xlsxwriter/format.h +8 -8
  56. data/libxlsxwriter/include/xlsxwriter/hash_table.h +1 -1
  57. data/libxlsxwriter/include/xlsxwriter/packager.h +18 -8
  58. data/libxlsxwriter/include/xlsxwriter/relationships.h +2 -2
  59. data/libxlsxwriter/include/xlsxwriter/shared_strings.h +5 -3
  60. data/libxlsxwriter/include/xlsxwriter/styles.h +10 -5
  61. data/libxlsxwriter/include/xlsxwriter/theme.h +2 -2
  62. data/libxlsxwriter/include/xlsxwriter/utility.h +35 -5
  63. data/libxlsxwriter/include/xlsxwriter/workbook.h +234 -57
  64. data/libxlsxwriter/include/xlsxwriter/worksheet.h +780 -91
  65. data/libxlsxwriter/include/xlsxwriter/xmlwriter.h +4 -2
  66. data/libxlsxwriter/libxlsxwriter.podspec +4 -2
  67. data/libxlsxwriter/src/Makefile +31 -6
  68. data/libxlsxwriter/src/app.c +2 -2
  69. data/libxlsxwriter/src/chart.c +116 -23
  70. data/libxlsxwriter/src/chartsheet.c +508 -0
  71. data/libxlsxwriter/src/content_types.c +12 -4
  72. data/libxlsxwriter/src/core.c +11 -11
  73. data/libxlsxwriter/src/custom.c +3 -3
  74. data/libxlsxwriter/src/drawing.c +114 -17
  75. data/libxlsxwriter/src/format.c +5 -5
  76. data/libxlsxwriter/src/hash_table.c +1 -1
  77. data/libxlsxwriter/src/packager.c +378 -61
  78. data/libxlsxwriter/src/relationships.c +2 -2
  79. data/libxlsxwriter/src/shared_strings.c +18 -4
  80. data/libxlsxwriter/src/styles.c +59 -12
  81. data/libxlsxwriter/src/theme.c +2 -2
  82. data/libxlsxwriter/src/utility.c +93 -6
  83. data/libxlsxwriter/src/workbook.c +379 -61
  84. data/libxlsxwriter/src/worksheet.c +1240 -174
  85. data/libxlsxwriter/src/xmlwriter.c +18 -9
  86. data/libxlsxwriter/third_party/minizip/Makefile +6 -1
  87. data/libxlsxwriter/third_party/minizip/ioapi.c +10 -0
  88. data/libxlsxwriter/third_party/minizip/zip.c +2 -0
  89. data/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.c +2 -2
  90. data/libxlsxwriter/version.txt +1 -1
  91. data/test/auto_width_test.rb +19 -0
  92. data/test/date_test.rb +34 -0
  93. data/test/format_test.rb +8 -0
  94. data/test/reopen_test.rb +22 -0
  95. data/test/test_helper.rb +8 -5
  96. data/test/text_width_test.rb +80 -0
  97. data/test/tmpfile_test.rb +1 -0
  98. data/test/validations_test.rb +47 -0
  99. data/test/worksheet_test.rb +44 -1
  100. metadata +33 -9
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Used in conjunction with the libxlsxwriter library.
5
5
  *
6
- * Copyright 2014-2017, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
6
+ * Copyright 2014-2019, John McNamara, jmcnamara@cpan.org. See LICENSE.txt.
7
7
  *
8
8
  */
9
9
 
@@ -140,6 +140,15 @@ lxw_xml_data_element(FILE * xmlfile,
140
140
  fprintf(xmlfile, "</%s>", tag);
141
141
  }
142
142
 
143
+ /*
144
+ * Write an XML <si> element for rich strings, without encoding.
145
+ */
146
+ void
147
+ lxw_xml_rich_si_element(FILE * xmlfile, const char *string)
148
+ {
149
+ fprintf(xmlfile, "<si>%s</si>", string);
150
+ }
151
+
143
152
  /*
144
153
  * Escape XML characters in attributes.
145
154
  */
@@ -153,19 +162,19 @@ _escape_attributes(struct xml_attribute *attribute)
153
162
  while (*p_attr) {
154
163
  switch (*p_attr) {
155
164
  case '&':
156
- strncat(p_encoded, LXW_AMP, sizeof(LXW_AMP) - 1);
165
+ memcpy(p_encoded, LXW_AMP, sizeof(LXW_AMP) - 1);
157
166
  p_encoded += sizeof(LXW_AMP) - 1;
158
167
  break;
159
168
  case '<':
160
- strncat(p_encoded, LXW_LT, sizeof(LXW_LT) - 1);
169
+ memcpy(p_encoded, LXW_LT, sizeof(LXW_LT) - 1);
161
170
  p_encoded += sizeof(LXW_LT) - 1;
162
171
  break;
163
172
  case '>':
164
- strncat(p_encoded, LXW_GT, sizeof(LXW_GT) - 1);
173
+ memcpy(p_encoded, LXW_GT, sizeof(LXW_GT) - 1);
165
174
  p_encoded += sizeof(LXW_GT) - 1;
166
175
  break;
167
176
  case '"':
168
- strncat(p_encoded, LXW_QUOT, sizeof(LXW_QUOT) - 1);
177
+ memcpy(p_encoded, LXW_QUOT, sizeof(LXW_QUOT) - 1);
169
178
  p_encoded += sizeof(LXW_QUOT) - 1;
170
179
  break;
171
180
  default:
@@ -195,15 +204,15 @@ lxw_escape_data(const char *data)
195
204
  while (*data) {
196
205
  switch (*data) {
197
206
  case '&':
198
- strncat(p_encoded, LXW_AMP, sizeof(LXW_AMP) - 1);
207
+ memcpy(p_encoded, LXW_AMP, sizeof(LXW_AMP) - 1);
199
208
  p_encoded += sizeof(LXW_AMP) - 1;
200
209
  break;
201
210
  case '<':
202
- strncat(p_encoded, LXW_LT, sizeof(LXW_LT) - 1);
211
+ memcpy(p_encoded, LXW_LT, sizeof(LXW_LT) - 1);
203
212
  p_encoded += sizeof(LXW_LT) - 1;
204
213
  break;
205
214
  case '>':
206
- strncat(p_encoded, LXW_GT, sizeof(LXW_GT) - 1);
215
+ memcpy(p_encoded, LXW_GT, sizeof(LXW_GT) - 1);
207
216
  p_encoded += sizeof(LXW_GT) - 1;
208
217
  break;
209
218
  default:
@@ -349,7 +358,7 @@ lxw_new_attribute_dbl(const char *key, double value)
349
358
  struct xml_attribute *attribute = malloc(sizeof(struct xml_attribute));
350
359
 
351
360
  LXW_ATTRIBUTE_COPY(attribute->key, key);
352
- lxw_snprintf(attribute->value, LXW_MAX_ATTRIBUTE_LENGTH, "%.16g", value);
361
+ lxw_sprintf_dbl(attribute->value, value);
353
362
 
354
363
  return attribute;
355
364
  }
@@ -9,7 +9,7 @@ ifdef V
9
9
  Q=
10
10
  endif
11
11
 
12
- UNAME := $(shell uname)
12
+ UNAME := $(shell uname -sr)
13
13
 
14
14
  # Check for MinGW/MinGW64/Cygwin environments.
15
15
  ifneq (,$(findstring MINGW, $(UNAME)))
@@ -32,6 +32,11 @@ CC = gcc
32
32
  CFLAGS += -DUSE_FILE32API
33
33
  endif
34
34
 
35
+ # Fix for modified zconf.h on Gentoo.
36
+ ifneq (,$(findstring gentoo, $(UNAME)))
37
+ CFLAGS += -DOF=_Z_OF
38
+ endif
39
+
35
40
  all: ioapi.o zip.o ioapi.so zip.so
36
41
 
37
42
  %.o : %.c
@@ -96,6 +96,7 @@ static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, in
96
96
  {
97
97
  FILE* file = NULL;
98
98
  const char* mode_fopen = NULL;
99
+ (void) opaque;
99
100
  if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
100
101
  mode_fopen = "rb";
101
102
  else
@@ -114,6 +115,7 @@ static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename,
114
115
  {
115
116
  FILE* file = NULL;
116
117
  const char* mode_fopen = NULL;
118
+ (void) opaque;
117
119
  if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
118
120
  mode_fopen = "rb";
119
121
  else
@@ -132,6 +134,7 @@ static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename,
132
134
  static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size)
133
135
  {
134
136
  uLong ret;
137
+ (void) opaque;
135
138
  ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
136
139
  return ret;
137
140
  }
@@ -139,6 +142,7 @@ static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf,
139
142
  static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size)
140
143
  {
141
144
  uLong ret;
145
+ (void) opaque;
142
146
  ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
143
147
  return ret;
144
148
  }
@@ -146,6 +150,7 @@ static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const voi
146
150
  static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream)
147
151
  {
148
152
  long ret;
153
+ (void) opaque;
149
154
  ret = ftell((FILE *)stream);
150
155
  return ret;
151
156
  }
@@ -154,6 +159,7 @@ static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream)
154
159
  static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream)
155
160
  {
156
161
  ZPOS64_T ret;
162
+ (void) opaque;
157
163
  ret = FTELLO_FUNC((FILE *)stream);
158
164
  return ret;
159
165
  }
@@ -162,6 +168,7 @@ static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offs
162
168
  {
163
169
  int fseek_origin=0;
164
170
  long ret;
171
+ (void) opaque;
165
172
  switch (origin)
166
173
  {
167
174
  case ZLIB_FILEFUNC_SEEK_CUR :
@@ -185,6 +192,7 @@ static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T
185
192
  {
186
193
  int fseek_origin=0;
187
194
  long ret;
195
+ (void) opaque;
188
196
  switch (origin)
189
197
  {
190
198
  case ZLIB_FILEFUNC_SEEK_CUR :
@@ -210,6 +218,7 @@ static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T
210
218
  static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream)
211
219
  {
212
220
  int ret;
221
+ (void) opaque;
213
222
  ret = fclose((FILE *)stream);
214
223
  return ret;
215
224
  }
@@ -217,6 +226,7 @@ static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream)
217
226
  static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream)
218
227
  {
219
228
  int ret;
229
+ (void) opaque;
220
230
  ret = ferror((FILE *)stream);
221
231
  return ret;
222
232
  }
@@ -519,12 +519,14 @@ local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_f
519
519
  break;
520
520
 
521
521
  for (i=(int)uReadSize-3; (i--)>0;)
522
+ {
522
523
  if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
523
524
  ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
524
525
  {
525
526
  uPosFound = uReadPos+i;
526
527
  break;
527
528
  }
529
+ }
528
530
 
529
531
  if (uPosFound!=0)
530
532
  break;
@@ -169,7 +169,7 @@ static char *getenv_save(const char *varname, char *buf, size_t bufsize)
169
169
  buf[0] = '\0';
170
170
  if (ptr)
171
171
  {
172
- strncpy(buf, ptr, bufsize);
172
+ strncpy(buf, ptr, bufsize-1);
173
173
  buf[bufsize-1] = '\0';
174
174
  return buf;
175
175
  }
@@ -189,7 +189,7 @@ static FILE *mktempfile_internal(const char *tmpdir, const char *pfx, char **tmp
189
189
  */
190
190
  {
191
191
  FILE *fp;
192
- int fd;
192
+ int fd = 0;
193
193
  char randpart[] = "1234567890";
194
194
  size_t lentempname;
195
195
  int i;
@@ -1 +1 @@
1
- 2017-02-28 20:35:27 +0800 c8064ee
1
+ 2019-06-17 01:19:43 +0800 56b73bb
@@ -0,0 +1,19 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe "FastExcel text_width" do
4
+
5
+ it "should calculate text width" do
6
+ workbook = FastExcel.open(constant_memory: false)
7
+ sheet = workbook.add_worksheet
8
+ sheet.auto_width = true
9
+
10
+ sheet.append_row([
11
+ "tini",
12
+ "Longer",
13
+ "Some longer text!",
14
+ "This gem is FFI binding for libxlsxwriter C library"
15
+ ])
16
+
17
+ assert_equal(sheet.calculated_column_widths, {0 => 3.52, 1 => 5.28, 2 => 14.96, 3 => 44.88})
18
+ end
19
+ end
data/test/date_test.rb CHANGED
@@ -20,3 +20,37 @@ describe "FastExcel.date_num" do
20
20
  end
21
21
 
22
22
  end
23
+
24
+ describe "FastExcel.write_value" do
25
+
26
+ it "should save correct datetime" do
27
+ workbook = FastExcel.open(constant_memory: true)
28
+ worksheet = workbook.add_worksheet
29
+
30
+ format = workbook.number_format("yyyy-mm-dd hh:mm:ss")
31
+ value = DateTime.parse('2017-03-01 15:15:15 +0000')
32
+
33
+ worksheet.write_value(0, 0, value, format)
34
+ workbook.close
35
+
36
+ data = parse_xlsx_as_matrix(workbook.filename)
37
+
38
+ assert_equal(data[0][0], value)
39
+ end
40
+
41
+ it "should save correct date" do
42
+ workbook = FastExcel.open(constant_memory: true)
43
+ worksheet = workbook.add_worksheet
44
+
45
+ format = workbook.number_format("yyyy-mm-dd")
46
+ value = Date.parse('2017-03-01')
47
+
48
+ worksheet.write_value(0, 0, value, format)
49
+ workbook.close
50
+
51
+ data = parse_xlsx_as_matrix(workbook.filename)
52
+
53
+ assert_equal(data[0][0], value)
54
+ end
55
+
56
+ end
data/test/format_test.rb CHANGED
@@ -168,4 +168,12 @@ describe "FastExcel::FormatExt border" do
168
168
  assert_equal(:border_thin, @format.border_bottom)
169
169
  end
170
170
 
171
+ it "should define aliases" do
172
+ @format.font_size = 20
173
+ assert_equal(@format.font_size, 20)
174
+
175
+ @format.font_name = "XXX"
176
+ assert_equal(@format.font_name, "XXX")
177
+ end
178
+
171
179
  end
@@ -0,0 +1,22 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe "FastExcel::Worksheet" do
4
+
5
+ it "should get_worksheet_by_name" do
6
+ workbook = FastExcel.open(constant_memory: false)
7
+ workbook.add_worksheet("Page1")
8
+
9
+ ws = workbook.get_worksheet_by_name("Page1")
10
+ ws.write_row(0, ['1'])
11
+
12
+ workbook.close
13
+
14
+ error = assert_raises do
15
+ FastExcel.open(workbook.filename, constant_memory: false)
16
+ end
17
+
18
+ assert_equal(error.class, ArgumentError)
19
+ assert_equal(error.message, "File '#{workbook.filename}' already exists. FastExcel can not open existing files, only create new files")
20
+ end
21
+
22
+ end
data/test/test_helper.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'bundler/setup'
2
2
  require 'minitest/autorun'
3
3
  require "minitest/reporters"
4
+ require 'pp'
4
5
 
5
6
  ##Encoding.default_external = Encoding::UTF_8
6
7
  ##Encoding.default_internal = Encoding::UTF_8
@@ -40,12 +41,14 @@ def parse_xlsx_as_matrix(file_path)
40
41
  sheet = excel.sheet(0)
41
42
 
42
43
  rows = []
43
- 1.upto(sheet.last_row) do |row_number|
44
- row = 1.upto(sheet.last_column).map do |col|
45
- sheet.cell(row_number, col)
46
- end
44
+ if sheet.last_row
45
+ 1.upto(sheet.last_row) do |row_number|
46
+ row = 1.upto(sheet.last_column).map do |col|
47
+ sheet.cell(row_number, col)
48
+ end
47
49
 
48
- rows << row
50
+ rows << row
51
+ end
49
52
  end
50
53
 
51
54
  return rows
@@ -0,0 +1,80 @@
1
+ require_relative 'test_helper'
2
+
3
+
4
+ describe "FastExcel Arial text_width" do
5
+
6
+ before do
7
+ skip "Use basic width calc for now"
8
+ end
9
+
10
+ it "should calculate width for character" do
11
+ assert_in_delta(FastExcel.arial_text_width('a'), 55.61, 0.1)
12
+ end
13
+
14
+ it "should calculate width with kerning" do
15
+ assert_in_delta(FastExcel.arial_text_width('A'), 66.69, 0.1)
16
+ assert_in_delta(FastExcel.arial_text_width('V'), 66.69, 0.1)
17
+
18
+ assert_in_delta(FastExcel.arial_text_width('AV'), 125.97, 0.1)
19
+
20
+ assert_in_delta(FastExcel.arial_text_width('11'), 103.80, 0.1)
21
+ end
22
+
23
+ it "should skip system characters" do
24
+ assert_in_delta(FastExcel.arial_text_width(10.chr), 0.0)
25
+ end
26
+
27
+ it "should handle multiline text" do
28
+ assert_in_delta(FastExcel.arial_text_width("More\nThen\nOne Line"), 405.85, 0.1)
29
+ end
30
+ end
31
+
32
+ describe "FastExcel Calibri text_width" do
33
+
34
+ before do
35
+ skip "Use basic width calc for now"
36
+ end
37
+
38
+ it "should calculate width for character" do
39
+ assert_in_delta(FastExcel.calibri_text_width('a'), 47.90, 0.1)
40
+ end
41
+
42
+ it "should calculate width with kerning" do
43
+ assert_in_delta(FastExcel.calibri_text_width('A'), 57.86, 0.1)
44
+ assert_in_delta(FastExcel.calibri_text_width('V'), 56.73, 0.1)
45
+
46
+ assert_in_delta(FastExcel.calibri_text_width('AV'), 110.25, 0.1)
47
+
48
+ assert_in_delta(FastExcel.calibri_text_width('11'), 101.36, 0.1)
49
+ end
50
+
51
+ it "should skip system characters" do
52
+ assert_in_delta(FastExcel.calibri_text_width(10.chr), 0.0)
53
+ end
54
+
55
+ end
56
+
57
+ describe "FastExcel Times New Roman text_width" do
58
+
59
+ before do
60
+ skip "Use basic width calc for now"
61
+ end
62
+
63
+ it "should calculate width for character" do
64
+ assert_in_delta(FastExcel.times_new_roman_text_width('a'), 44.38, 0.1)
65
+ end
66
+
67
+ it "should calculate width with kerning" do
68
+ assert_in_delta(FastExcel.times_new_roman_text_width('A'), 72.21, 0.1)
69
+ assert_in_delta(FastExcel.times_new_roman_text_width('V'), 72.21, 0.1)
70
+
71
+ assert_in_delta(FastExcel.times_new_roman_text_width('AV'), 131.54, 0.1)
72
+
73
+ assert_in_delta(FastExcel.times_new_roman_text_width('11'), 96.28, 0.1)
74
+ end
75
+
76
+ it "should skip system characters" do
77
+ assert_in_delta(FastExcel.times_new_roman_text_width(10.chr), 0.0)
78
+ end
79
+
80
+ end
data/test/tmpfile_test.rb CHANGED
@@ -17,6 +17,7 @@ describe "FastExcel" do
17
17
  workbook.read_string
18
18
 
19
19
  refute(File.exist?(workbook.filename))
20
+ refute(File.exist?(File.dirname(workbook.filename)))
20
21
  refute(workbook.is_open)
21
22
  end
22
23
 
@@ -0,0 +1,47 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe "FastExcel validations" do
4
+
5
+ it "should raise error when duplicate sheet name" do
6
+ workbook = FastExcel.open(constant_memory: true)
7
+
8
+ workbook.add_worksheet("Payments Report")
9
+ error = assert_raises do
10
+ workbook.add_worksheet("Payments Report")
11
+ end
12
+
13
+ assert_equal(ArgumentError, error.class)
14
+ assert_equal("Worksheet name 'Payments Report' is already in use", error.message)
15
+ end
16
+
17
+ 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()
22
+ ws2.write_value(0, 2, "aaa")
23
+
24
+ assert_equal("Sheet1", ws1[:name])
25
+ assert_equal("Sheet2", ws2[:name])
26
+ end
27
+
28
+ it "should raise error when the sheet name exceeds maximum length" do
29
+ workbook = FastExcel.open(constant_memory: true)
30
+
31
+ error = assert_raises do
32
+ workbook.add_worksheet("ABCDEFGHIJKLMNOPQRSTUVWXYZ012345")
33
+ end
34
+
35
+ assert_equal(ArgumentError, error.class)
36
+ assert_equal("Worksheet name 'ABCDEFGHIJKLMNOPQRSTUVWXYZ012345' exceeds Excel's limit of 31 characters", error.message)
37
+ end
38
+
39
+ 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")
43
+ worksheet.append_row(["aaa", "bbb", "ccc"])
44
+
45
+ assert_equal("ABCDEFGHIJKLMNOPQRSTUVWXYZ01234", worksheet[:name])
46
+ end
47
+ end