fast_excel 0.2.2 → 0.4.0

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