xlsxwriter 0.2.0.pre → 0.2.0.pre.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +1 -1
- data/ext/xlsxwriter/chart.h +1 -1
- data/ext/xlsxwriter/format.h +1 -1
- data/ext/xlsxwriter/rich_string.c +85 -0
- data/ext/xlsxwriter/rich_string.h +12 -0
- data/ext/xlsxwriter/workbook.c +7 -13
- data/ext/xlsxwriter/workbook.h +0 -1
- data/ext/xlsxwriter/workbook_properties.c +1 -1
- data/ext/xlsxwriter/worksheet.c +63 -5
- data/ext/xlsxwriter/worksheet.h +1 -1
- data/ext/xlsxwriter/xlsxwriter.c +4 -2
- data/ext/xlsxwriter/xlsxwriter_ext.h +2 -2
- data/lib/xlsxwriter.rb +3 -1
- data/lib/xlsxwriter/error.rb +19 -0
- data/lib/xlsxwriter/rich_string.rb +69 -0
- data/lib/xlsxwriter/version.rb +1 -1
- data/lib/xlsxwriter/worksheet.rb +87 -76
- data/test/support/with_xlsx_file.rb +13 -0
- data/test/support/xlsx_comparable.rb +21 -22
- data/test/test-data-validation.rb +1 -1
- data/test/test-errors.rb +19 -7
- data/test/test-escapes.rb +11 -0
- data/test/test-optimize.rb +43 -0
- data/test/test-rich-string.rb +159 -0
- data/test/test-ruby-worksheet.rb +33 -0
- data/test/xlsx-func-testcase.rb +9 -9
- metadata +18 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 851dae6d52bb43129e9a28421a8f9bdffcce9fffe682106f53d6adbed52d2d81
|
4
|
+
data.tar.gz: a7587dbc467434582ad1a89dcaa31d6070d71703551f1b70f2b0ff94a830c152
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6a30288f6cdef1492a37cfdb8e0627b47e9be3bdcece23fb43713e098894979c0549fc05e22f796f5cc3913f9849b82dae1bc64417bfbcefe6936c47bbf3808b
|
7
|
+
data.tar.gz: eb3a75578949b0d1a2f606686886fd1718abf6791ce9853a04e41fb126d1326dc95517d4bfd23667ca09c1f990e23f6fd57ffd69a5f3168c154ea71d9bc41e74
|
data/Rakefile
CHANGED
@@ -7,7 +7,7 @@ spec = Gem::Specification.load('xlsxwriter.gemspec')
|
|
7
7
|
Rake::ExtensionTask.new('xlsxwriter', spec) do |ext|
|
8
8
|
ext.lib_dir = 'lib/xlsxwriter'
|
9
9
|
end
|
10
|
-
|
10
|
+
Rake::Task['compile'].prerequisites.unshift :patch_dep
|
11
11
|
|
12
12
|
Gem::PackageTask.new(spec) do |pkg|
|
13
13
|
end
|
data/ext/xlsxwriter/chart.h
CHANGED
data/ext/xlsxwriter/format.h
CHANGED
@@ -0,0 +1,85 @@
|
|
1
|
+
#include <ruby/util.h>
|
2
|
+
#include "rich_string.h"
|
3
|
+
#include "workbook.h"
|
4
|
+
#include "xlsxwriter_ext.h"
|
5
|
+
|
6
|
+
VALUE cRichString;
|
7
|
+
|
8
|
+
void rich_string_free(void *p);
|
9
|
+
|
10
|
+
|
11
|
+
VALUE
|
12
|
+
rich_string_alloc(VALUE klass) {
|
13
|
+
VALUE obj;
|
14
|
+
lxw_rich_string_tuple **ptr;
|
15
|
+
|
16
|
+
obj = Data_Make_Struct(klass, lxw_rich_string_tuple *, NULL, rich_string_free, ptr);
|
17
|
+
*ptr = NULL;
|
18
|
+
|
19
|
+
return obj;
|
20
|
+
}
|
21
|
+
|
22
|
+
void
|
23
|
+
rich_string_free(void *p) {
|
24
|
+
lxw_rich_string_tuple **ptr = p;
|
25
|
+
if (*ptr) {
|
26
|
+
ruby_xfree(*ptr);
|
27
|
+
*ptr = NULL;
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
VALUE
|
32
|
+
rich_string_cached_p(VALUE self) {
|
33
|
+
lxw_rich_string_tuple **ptr;
|
34
|
+
Data_Get_Struct(self, lxw_rich_string_tuple *, ptr);
|
35
|
+
|
36
|
+
if (*ptr) {
|
37
|
+
return Qtrue;
|
38
|
+
} else {
|
39
|
+
return Qfalse;
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
lxw_rich_string_tuple **
|
44
|
+
serialize_rich_string(VALUE rs) {
|
45
|
+
VALUE arr = rb_funcall(rs, rb_intern("parts"), 0);
|
46
|
+
VALUE wb = rb_funcall(rs, rb_intern("workbook"), 0);
|
47
|
+
|
48
|
+
int len = RARRAY_LEN(arr);
|
49
|
+
|
50
|
+
lxw_rich_string_tuple **ptr;
|
51
|
+
Data_Get_Struct(rs, lxw_rich_string_tuple *, ptr);
|
52
|
+
|
53
|
+
if (*ptr) { // cached
|
54
|
+
return (lxw_rich_string_tuple **) *ptr;
|
55
|
+
}
|
56
|
+
|
57
|
+
rb_obj_freeze(arr);
|
58
|
+
*ptr = ruby_xmalloc(sizeof(lxw_rich_string_tuple) * len + sizeof(lxw_rich_string_tuple *) * (len + 1));
|
59
|
+
lxw_rich_string_tuple **res = *(lxw_rich_string_tuple ***)ptr;
|
60
|
+
|
61
|
+
lxw_rich_string_tuple *base_ptr = ((void *)*ptr + sizeof(lxw_rich_string_tuple *) * (len + 1));
|
62
|
+
for (int i = 0; i < len; ++i) {
|
63
|
+
VALUE part = rb_ary_entry(arr, i);
|
64
|
+
VALUE text = rb_ary_entry(part, 0);
|
65
|
+
VALUE format = rb_ary_entry(part, 1);
|
66
|
+
|
67
|
+
base_ptr[i].format = workbook_get_format(wb, format);
|
68
|
+
base_ptr[i].string = StringValueCStr(text);
|
69
|
+
res[i] = &base_ptr[i];
|
70
|
+
}
|
71
|
+
res[len] = NULL;
|
72
|
+
|
73
|
+
return res;
|
74
|
+
}
|
75
|
+
|
76
|
+
|
77
|
+
void init_xlsxwriter_rich_string() {
|
78
|
+
#if 0
|
79
|
+
// Making RDoc happy.
|
80
|
+
mXlsxWriter = rb_define_module("XlsxWriter");
|
81
|
+
#endif
|
82
|
+
cRichString = rb_define_class_under(mXlsxWriter, "RichString", rb_cObject);
|
83
|
+
rb_define_alloc_func(cRichString, rich_string_alloc);
|
84
|
+
rb_define_private_method(cRichString, "cached?", rich_string_cached_p, 0);
|
85
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <xlsxwriter.h>
|
3
|
+
|
4
|
+
#ifndef __RICH_STRING__
|
5
|
+
#define __RICH_STRING__
|
6
|
+
|
7
|
+
void init_xlsxwriter_rich_string();
|
8
|
+
lxw_rich_string_tuple **serialize_rich_string(VALUE rs);
|
9
|
+
|
10
|
+
extern VALUE cRichString;
|
11
|
+
|
12
|
+
#endif /* RICH_STRING_H */
|
data/ext/xlsxwriter/workbook.c
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#include <string.h>
|
2
2
|
#include <ruby.h>
|
3
3
|
#include <ruby/thread.h>
|
4
|
-
#include
|
4
|
+
#include <xlsxwriter.h>
|
5
5
|
#include "chart.h"
|
6
6
|
#include "format.h"
|
7
7
|
#include "workbook.h"
|
@@ -353,25 +353,19 @@ value_to_lxw_datetime(VALUE val) {
|
|
353
353
|
val = rb_funcall(val, i_to_time, 0);
|
354
354
|
}
|
355
355
|
VALUE time_a = rb_funcall(val, rb_intern("to_a"), 0);
|
356
|
-
static const VALUE idxs[6] = { INT2FIX(0), INT2FIX(1), INT2FIX(2), INT2FIX(3), INT2FIX(4), INT2FIX(5) };
|
357
356
|
lxw_datetime res = {
|
358
|
-
.year = NUM2INT(
|
359
|
-
.month = NUM2INT(
|
360
|
-
.day = NUM2INT(
|
361
|
-
.hour = NUM2INT(
|
362
|
-
.min = NUM2INT(
|
363
|
-
.sec = NUM2DBL(
|
357
|
+
.year = NUM2INT(rb_ary_entry(time_a, 5)),
|
358
|
+
.month = NUM2INT(rb_ary_entry(time_a, 4)),
|
359
|
+
.day = NUM2INT(rb_ary_entry(time_a, 3)),
|
360
|
+
.hour = NUM2INT(rb_ary_entry(time_a, 2)),
|
361
|
+
.min = NUM2INT(rb_ary_entry(time_a, 1)),
|
362
|
+
.sec = NUM2DBL(rb_ary_entry(time_a, 0)) +
|
364
363
|
NUM2DBL(rb_funcall(val, rb_intern("subsec"), 0))
|
365
364
|
};
|
366
365
|
|
367
366
|
return res;
|
368
367
|
}
|
369
368
|
|
370
|
-
void
|
371
|
-
handle_lxw_error(lxw_error err) {
|
372
|
-
return;
|
373
|
-
}
|
374
|
-
|
375
369
|
|
376
370
|
/* Document-class: XlsxWriter::Workbook
|
377
371
|
*
|
data/ext/xlsxwriter/workbook.h
CHANGED
data/ext/xlsxwriter/worksheet.c
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#include "chart.h"
|
2
|
+
#include "rich_string.h"
|
2
3
|
#include "worksheet.h"
|
3
4
|
#include "workbook.h"
|
4
5
|
#include "xlsxwriter_ext.h"
|
@@ -69,7 +70,7 @@ worksheet_init(int argc, VALUE *argv, VALUE self) {
|
|
69
70
|
Data_Get_Struct(argv[0], struct workbook, wb_ptr);
|
70
71
|
ptr->worksheet = workbook_add_worksheet(wb_ptr->workbook, name);
|
71
72
|
if (!ptr->worksheet)
|
72
|
-
rb_raise(
|
73
|
+
rb_raise(eXlsxWriterError, "worksheet was not created");
|
73
74
|
return self;
|
74
75
|
}
|
75
76
|
|
@@ -401,7 +402,8 @@ worksheet_write_blank_(int argc, VALUE *argv, VALUE self) {
|
|
401
402
|
*
|
402
403
|
* Writes a +formula+ with +value+ into a +cell+ with +format+.
|
403
404
|
*/
|
404
|
-
VALUE
|
405
|
+
VALUE
|
406
|
+
worksheet_write_formula_num_(int argc, VALUE *argv, VALUE self) {
|
405
407
|
lxw_row_t row;
|
406
408
|
lxw_col_t col;
|
407
409
|
VALUE formula = Qnil;
|
@@ -435,6 +437,53 @@ VALUE worksheet_write_formula_num_(int argc, VALUE *argv, VALUE self) {
|
|
435
437
|
return self;
|
436
438
|
}
|
437
439
|
|
440
|
+
/* call-seq:
|
441
|
+
* ws.write_rich_string(cell, value) -> self
|
442
|
+
* ws.write_rich_string(row, col, value) -> self
|
443
|
+
*
|
444
|
+
* Writes a +rich_string+ value into a +cell+.
|
445
|
+
*/
|
446
|
+
VALUE
|
447
|
+
worksheet_write_rich_string_(int argc, VALUE *argv, VALUE self) {
|
448
|
+
lxw_row_t row;
|
449
|
+
lxw_col_t col;
|
450
|
+
VALUE value = Qnil;
|
451
|
+
VALUE format_key = Qnil;
|
452
|
+
|
453
|
+
rb_check_arity(argc, 2, 4);
|
454
|
+
int larg = extract_cell(argc, argv, &row, &col);
|
455
|
+
VALUE workbook = rb_iv_get(self, "@workbook");
|
456
|
+
|
457
|
+
if (larg < argc) {
|
458
|
+
value = argv[larg];
|
459
|
+
if (TYPE(value) == T_ARRAY)
|
460
|
+
value = rb_funcall(cRichString, rb_intern("new"), 2, workbook, value);
|
461
|
+
else if (rb_class_of(value) != cRichString) {
|
462
|
+
rb_raise(rb_eArgError, "Wrong type of value: %"PRIsVALUE, rb_class_of(value));
|
463
|
+
}
|
464
|
+
++larg;
|
465
|
+
}
|
466
|
+
|
467
|
+
if (larg < argc) {
|
468
|
+
format_key = argv[larg];
|
469
|
+
++larg;
|
470
|
+
}
|
471
|
+
|
472
|
+
if (NIL_P(value)) {
|
473
|
+
rb_raise(rb_eArgError, "No value specified");
|
474
|
+
}
|
475
|
+
|
476
|
+
struct worksheet *ptr;
|
477
|
+
lxw_format *format = workbook_get_format(workbook, format_key);
|
478
|
+
lxw_rich_string_tuple **rich_string = serialize_rich_string(value);
|
479
|
+
if (rich_string) {
|
480
|
+
Data_Get_Struct(self, struct worksheet, ptr);
|
481
|
+
lxw_error err = worksheet_write_rich_string(ptr->worksheet, row, col, rich_string, format);
|
482
|
+
handle_lxw_error(err);
|
483
|
+
}
|
484
|
+
return self;
|
485
|
+
}
|
486
|
+
|
438
487
|
/* call-seq: ws.set_row(row, height: nil, format: nil, hide: false) -> self
|
439
488
|
*
|
440
489
|
* Set properties of the row.
|
@@ -693,7 +742,8 @@ worksheet_autofilter_(int argc, VALUE *argv, VALUE self) {
|
|
693
742
|
*
|
694
743
|
* Set the worksheet to be active on opening the workbook.
|
695
744
|
*/
|
696
|
-
VALUE
|
745
|
+
VALUE
|
746
|
+
worksheet_activate_(VALUE self) {
|
697
747
|
struct worksheet *ptr;
|
698
748
|
Data_Get_Struct(self, struct worksheet, ptr);
|
699
749
|
worksheet_activate(ptr->worksheet);
|
@@ -704,7 +754,8 @@ VALUE worksheet_activate_(VALUE self) {
|
|
704
754
|
*
|
705
755
|
* Set the worksheet to be selected on openong the workbook.
|
706
756
|
*/
|
707
|
-
VALUE
|
757
|
+
VALUE
|
758
|
+
worksheet_select_(VALUE self) {
|
708
759
|
struct worksheet *ptr;
|
709
760
|
Data_Get_Struct(self, struct worksheet, ptr);
|
710
761
|
worksheet_select(ptr->worksheet);
|
@@ -1426,7 +1477,7 @@ worksheet_data_validation_(int argc, VALUE *argv, VALUE self) {
|
|
1426
1477
|
free(data_validation.value_list);
|
1427
1478
|
}
|
1428
1479
|
|
1429
|
-
|
1480
|
+
handle_lxw_error(err);
|
1430
1481
|
|
1431
1482
|
return self;
|
1432
1483
|
}
|
@@ -1444,6 +1495,11 @@ value_to_col(VALUE value) {
|
|
1444
1495
|
}
|
1445
1496
|
}
|
1446
1497
|
|
1498
|
+
VALUE
|
1499
|
+
rb_extract_col(VALUE _self, VALUE col) {
|
1500
|
+
return INT2FIX(value_to_col(col));
|
1501
|
+
}
|
1502
|
+
|
1447
1503
|
int
|
1448
1504
|
extract_cell(int argc, VALUE *argv, lxw_row_t *row, lxw_col_t *col) {
|
1449
1505
|
char *str;
|
@@ -1563,6 +1619,7 @@ init_xlsxwriter_worksheet() {
|
|
1563
1619
|
rb_define_method(cWorksheet, "write_boolean", worksheet_write_boolean_, -1);
|
1564
1620
|
rb_define_method(cWorksheet, "write_blank", worksheet_write_blank_, -1);
|
1565
1621
|
rb_define_method(cWorksheet, "write_formula_num", worksheet_write_formula_num_, -1);
|
1622
|
+
rb_define_method(cWorksheet, "write_rich_string", worksheet_write_rich_string_, -1);
|
1566
1623
|
rb_define_method(cWorksheet, "set_row", worksheet_set_row_, 2);
|
1567
1624
|
rb_define_method(cWorksheet, "set_column", worksheet_set_column_, 3);
|
1568
1625
|
rb_define_method(cWorksheet, "insert_image", worksheet_insert_image_, -1);
|
@@ -1608,6 +1665,7 @@ init_xlsxwriter_worksheet() {
|
|
1608
1665
|
rb_define_method(cWorksheet, "vertical_dpi=", worksheet_set_vertical_dpi_, 1);
|
1609
1666
|
|
1610
1667
|
rb_define_method(cWorksheet, "add_data_validation", worksheet_data_validation_, -1);
|
1668
|
+
rb_define_private_method(cWorksheet, "extract_column", rb_extract_col, 1);
|
1611
1669
|
|
1612
1670
|
#define MAP_LXW_WH_CONST(name, val_name) rb_define_const(cWorksheet, #name, INT2NUM(LXW_##val_name))
|
1613
1671
|
#define MAP_LXW_WH_CONST1(name) MAP_LXW_WH_CONST(name, name)
|
data/ext/xlsxwriter/worksheet.h
CHANGED
data/ext/xlsxwriter/xlsxwriter.c
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
#include <ruby.h>
|
2
|
-
#include
|
2
|
+
#include <xlsxwriter.h>
|
3
3
|
#include "chart.h"
|
4
4
|
#include "format.h"
|
5
|
+
#include "rich_string.h"
|
5
6
|
#include "workbook.h"
|
6
7
|
#include "workbook_properties.h"
|
7
8
|
#include "worksheet.h"
|
@@ -33,11 +34,12 @@ void Init_xlsxwriter() {
|
|
33
34
|
mXlsxWriter = rb_define_module("XlsxWriter");
|
34
35
|
rbLibVersion = rb_str_new_cstr(lxw_version());
|
35
36
|
rb_define_const(mXlsxWriter, "LIBRARY_VERSION", rbLibVersion);
|
36
|
-
eXlsxWriterError =
|
37
|
+
eXlsxWriterError = rb_const_get(mXlsxWriter, rb_intern("Error"));
|
37
38
|
|
38
39
|
init_xlsxwriter_workbook();
|
39
40
|
init_xlsxwriter_workbook_properties();
|
40
41
|
init_xlsxwriter_format();
|
41
42
|
init_xlsxwriter_worksheet();
|
42
43
|
init_xlsxwriter_chart();
|
44
|
+
init_xlsxwriter_rich_string();
|
43
45
|
}
|
@@ -6,9 +6,9 @@
|
|
6
6
|
extern VALUE mXlsxWriter;
|
7
7
|
extern VALUE eXlsxWriterError;
|
8
8
|
|
9
|
-
inline void
|
9
|
+
inline void handle_lxw_error(lxw_error err) {
|
10
10
|
if (err) {
|
11
|
-
|
11
|
+
rb_exc_raise(rb_funcall(eXlsxWriterError, rb_intern("new"), 2, rb_str_new_cstr(lxw_strerror(err)), INT2NUM(err)));
|
12
12
|
}
|
13
13
|
}
|
14
14
|
|
data/lib/xlsxwriter.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module XlsxWriter
|
4
|
+
##
|
5
|
+
# An error returned from libxlsxwriter. Numeric code is accessible via #code
|
6
|
+
class Error < StandardError
|
7
|
+
# Error code
|
8
|
+
attr_reader :code
|
9
|
+
|
10
|
+
def initialize(msg, code = nil)
|
11
|
+
super(msg)
|
12
|
+
@code = code
|
13
|
+
end
|
14
|
+
|
15
|
+
def inspect
|
16
|
+
"#<#{self.class}: #{self}#{" (code: #{code})" if code}>"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module XlsxWriter
|
4
|
+
##
|
5
|
+
# RichString is a multipart string consting of sub-strings with format
|
6
|
+
class RichString
|
7
|
+
attr_reader :workbook, :parts
|
8
|
+
|
9
|
+
##
|
10
|
+
# call-seq:
|
11
|
+
# RichString.new(workbook, parts)
|
12
|
+
# RichString.new(workbook)
|
13
|
+
#
|
14
|
+
# Creates rich string that could be written to the +workbook+.
|
15
|
+
# +parts+ is an array of pairs string + format. If no format is needed
|
16
|
+
# for the part single string can be specified instead.
|
17
|
+
# For example: +['This is ', ['bold', :bold], [' and this is'], ['italic', :italic]]+
|
18
|
+
#
|
19
|
+
# If parts is not specified it could be populated later with #add_part.
|
20
|
+
#
|
21
|
+
# Please note that on writing additional validations are applied (e.g. string should not be empty).
|
22
|
+
# Please consult libxlsxwriter documentation for additional details.
|
23
|
+
def initialize(workbook, parts = [])
|
24
|
+
@workbook = workbook
|
25
|
+
@parts = parts.map! do |(str, format)|
|
26
|
+
make_part(str, format)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# call-seq:
|
32
|
+
# rs.add_part(str)
|
33
|
+
# rs.add_part(str, format)
|
34
|
+
#
|
35
|
+
# Adds part (string +str+ formatted with +format+) to the RichString +rs+.
|
36
|
+
#
|
37
|
+
# Please note, that no parts can be added to a rich string that has already been written once.
|
38
|
+
def add_part(str, format = nil)
|
39
|
+
raise Error, 'Cannot modify as the RichString has already been written to a workbook.' if cached?
|
40
|
+
|
41
|
+
parts << make_part(str, format)
|
42
|
+
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
def <<(part)
|
47
|
+
add_part(*Array(part))
|
48
|
+
end
|
49
|
+
|
50
|
+
def inspect
|
51
|
+
"#<#{self.class}:#{to_s.inspect}, @cached=#{@cached}>"
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_s
|
55
|
+
parts.map(&:first)
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
|
62
|
+
def make_part(str, format)
|
63
|
+
[
|
64
|
+
str.frozen? ? str.to_str : str.to_str.clone.freeze,
|
65
|
+
(format.to_sym if format)
|
66
|
+
].freeze
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/xlsxwriter/version.rb
CHANGED
data/lib/xlsxwriter/worksheet.rb
CHANGED
@@ -1,96 +1,107 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
# Last row number written with #add_row
|
5
|
-
attr_reader :current_row
|
3
|
+
module XlsxWriter
|
6
4
|
|
7
|
-
|
8
|
-
|
5
|
+
class Worksheet
|
6
|
+
# Last row number written with #add_row
|
7
|
+
attr_reader :current_row, :col_auto_widths
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
# Both +types+ and +style+ may be an array as well as a symbol.
|
13
|
-
# In the latter case they are applied to all cells in the +row+.
|
14
|
-
#
|
15
|
-
# +height+ is a Numeric that specifies the row height.
|
16
|
-
#
|
17
|
-
# If +skip_empty+ is set to +true+ empty cells are not added to the sheet.
|
18
|
-
# Otherwise they are added with type +:blank+.
|
19
|
-
def add_row(row, style: nil, height: nil, types: nil, skip_empty: false)
|
20
|
-
row_idx = @current_row ||= 0
|
21
|
-
@current_row += 1
|
9
|
+
# Thiner characters list used for column width logic mimicking axlsx behaviour
|
10
|
+
THIN_CHARS = '^.acfijklrstxzFIJL()-'.freeze
|
22
11
|
|
23
|
-
|
24
|
-
|
12
|
+
# Write a +row+. If no +types+ passed XlsxWriter tries to deduce them automatically.
|
13
|
+
#
|
14
|
+
# Both +types+ and +style+ may be an array as well as a symbol.
|
15
|
+
# In the latter case they are applied to all cells in the +row+.
|
16
|
+
#
|
17
|
+
# +height+ is a Numeric that specifies the row height.
|
18
|
+
#
|
19
|
+
# If +skip_empty+ is set to +true+ empty cells are not added to the sheet.
|
20
|
+
# Otherwise they are added with type +:blank+.
|
21
|
+
def add_row(row, style: nil, height: nil, types: nil, skip_empty: false)
|
22
|
+
row_idx = @current_row ||= 0
|
23
|
+
@current_row += 1
|
25
24
|
|
26
|
-
|
27
|
-
|
28
|
-
cell_type = types_ary ? types_ary[idx] : types
|
25
|
+
style_ary = style if style.is_a?(Array)
|
26
|
+
types_ary = types if types.is_a?(Array)
|
29
27
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
write_number(row_idx, idx, value.to_f, cell_style)
|
37
|
-
when :formula
|
38
|
-
write_formula(row_idx, idx, value, cell_style)
|
39
|
-
when :datetime, :date, :time
|
40
|
-
write_datetime(row_idx, idx, value.to_time, cell_style)
|
41
|
-
when :url
|
42
|
-
write_url(row_idx, idx, value, cell_style)
|
43
|
-
update_col_auto_width(idx, value.to_s, cell_style)
|
44
|
-
when :boolean
|
45
|
-
write_boolean(row_idx, idx, value, cell_style)
|
46
|
-
when :blank
|
47
|
-
write_blank(row_idx, idx, cell_style)
|
48
|
-
when :skip, :empty
|
49
|
-
# write nothing
|
50
|
-
when nil
|
51
|
-
case value
|
52
|
-
when Numeric
|
53
|
-
write_number(row_idx, idx, value, cell_style)
|
54
|
-
when TrueClass, FalseClass
|
55
|
-
write_boolean(row_idx, idx, value, cell_style)
|
56
|
-
when Time, (defined?(Date) ? Date : Time)
|
57
|
-
write_datetime(row_idx, idx, value, cell_style)
|
58
|
-
when '', nil
|
59
|
-
write_blank(row_idx, idx, cell_style) unless skip_empty
|
60
|
-
when /\A=/
|
61
|
-
write_formula(row_idx, idx, value, cell_style)
|
62
|
-
when String
|
63
|
-
write_string(row_idx, idx, value, cell_style)
|
64
|
-
update_col_auto_width(idx, value, cell_style)
|
65
|
-
else # assume string
|
28
|
+
row.each_with_index do |value, idx|
|
29
|
+
cell_style = style_ary ? style_ary[idx] : style
|
30
|
+
cell_type = types_ary ? types_ary[idx] : types
|
31
|
+
|
32
|
+
case cell_type && cell_type.to_sym
|
33
|
+
when :string
|
66
34
|
value = value.to_s
|
67
35
|
write_string(row_idx, idx, value, cell_style)
|
68
36
|
update_col_auto_width(idx, value, cell_style)
|
37
|
+
when :rich_string
|
38
|
+
write_rich_string(row_idx, idx, value, cell_style)
|
39
|
+
when :number
|
40
|
+
write_number(row_idx, idx, value.to_f, cell_style)
|
41
|
+
when :formula
|
42
|
+
write_formula(row_idx, idx, value, cell_style)
|
43
|
+
when :datetime, :date, :time
|
44
|
+
write_datetime(row_idx, idx, value.to_time, cell_style)
|
45
|
+
when :url
|
46
|
+
write_url(row_idx, idx, value, cell_style)
|
47
|
+
update_col_auto_width(idx, value.to_s, cell_style)
|
48
|
+
when :boolean
|
49
|
+
write_boolean(row_idx, idx, value, cell_style)
|
50
|
+
when :blank
|
51
|
+
write_blank(row_idx, idx, cell_style)
|
52
|
+
when :skip, :empty
|
53
|
+
# write nothing
|
54
|
+
when nil
|
55
|
+
case value
|
56
|
+
when Numeric
|
57
|
+
write_number(row_idx, idx, value, cell_style)
|
58
|
+
when TrueClass, FalseClass
|
59
|
+
write_boolean(row_idx, idx, value, cell_style)
|
60
|
+
when Time, (defined?(Date) ? Date : Time)
|
61
|
+
write_datetime(row_idx, idx, value, cell_style)
|
62
|
+
when '', nil
|
63
|
+
write_blank(row_idx, idx, cell_style) unless skip_empty
|
64
|
+
when /\A=/
|
65
|
+
write_formula(row_idx, idx, value, cell_style)
|
66
|
+
when String
|
67
|
+
write_string(row_idx, idx, value, cell_style)
|
68
|
+
update_col_auto_width(idx, value, cell_style)
|
69
|
+
when RichString
|
70
|
+
write_rich_string(row_idx, idx, value, cell_style)
|
71
|
+
else # assume string
|
72
|
+
value = value.to_s
|
73
|
+
write_string(row_idx, idx, value, cell_style)
|
74
|
+
update_col_auto_width(idx, value, cell_style)
|
75
|
+
end
|
76
|
+
else
|
77
|
+
raise ArgumentError, "Unknown cell type #{cell_type}."
|
69
78
|
end
|
70
|
-
else
|
71
|
-
raise ArgumentError, "Unknown cell type #{cell_type}."
|
72
79
|
end
|
73
|
-
end
|
74
80
|
|
75
|
-
|
81
|
+
set_row(row_idx, height: height) if height
|
76
82
|
|
77
|
-
|
78
|
-
|
83
|
+
nil
|
84
|
+
end
|
79
85
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
86
|
+
# Apply cols automatic widths calculated by #add_row.
|
87
|
+
def apply_auto_widths
|
88
|
+
@col_auto_widths.each_with_index do |width, idx|
|
89
|
+
set_column(idx, idx, width: width) if width
|
90
|
+
end
|
84
91
|
end
|
85
|
-
end
|
86
92
|
|
87
|
-
|
93
|
+
def get_column_auto_width(col)
|
94
|
+
@col_auto_widths[extract_column(col)]
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
88
98
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
99
|
+
# Updates the col auto width value to fit the string.
|
100
|
+
def update_col_auto_width(idx, val, format)
|
101
|
+
font_scale = (@workbook.font_sizes[format] || 11) / 10.0
|
102
|
+
width = (val.count(THIN_CHARS) + 3) * font_scale
|
103
|
+
width = 255 if width > 255 # Max xlsx column width is 255 characters
|
104
|
+
@col_auto_widths[idx] = [@col_auto_widths[idx] || 0, width].max
|
105
|
+
end
|
95
106
|
end
|
96
107
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'xlsxwriter'
|
2
|
+
|
3
|
+
module WithXlsxFile
|
4
|
+
def with_xlsx_file(file_path = 'tmp/test.xlsx', **opts)
|
5
|
+
after = opts.delete :after
|
6
|
+
XlsxWriter::Workbook.open(file_path, opts) do |wb|
|
7
|
+
yield wb
|
8
|
+
end
|
9
|
+
after.call if after
|
10
|
+
ensure
|
11
|
+
File.delete file_path if File.exist? file_path
|
12
|
+
end
|
13
|
+
end
|
@@ -4,15 +4,16 @@ require 'test/unit'
|
|
4
4
|
require 'zip'
|
5
5
|
|
6
6
|
module XlsxComparable
|
7
|
-
def assert_xlsx_equal(got_path, exp_path, ignore_files=[], ignore_elements={})
|
7
|
+
def assert_xlsx_equal(got_path, exp_path, ignore_files = [], ignore_elements = {})
|
8
8
|
Zip::File.open(exp_path) do |exp_zip|
|
9
9
|
Zip::File.open(got_path) do |got_zip|
|
10
|
-
exp_files = exp_zip.glob('**/*').
|
11
|
-
got_files = got_zip.glob('**/*').
|
10
|
+
exp_files = exp_zip.glob('**/*').reject { |e| ignore_files.include?(e.name) }
|
11
|
+
got_files = got_zip.glob('**/*').reject { |e| ignore_files.include?(e.name) }
|
12
12
|
assert_equal(got_files.map(&:name).sort, exp_files.map(&:name).sort)
|
13
13
|
|
14
14
|
exp_files.each do |exp_entry|
|
15
15
|
next unless exp_entry.file?
|
16
|
+
|
16
17
|
exp_xml_str = exp_zip.read(exp_entry.name)
|
17
18
|
got_xml_str = got_zip.read(exp_entry.name)
|
18
19
|
|
@@ -32,20 +33,20 @@ module XlsxComparable
|
|
32
33
|
exp_xml_str.gsub!(/<calcPr[^>]*>/, '<calcPr/>')
|
33
34
|
got_xml_str.gsub!(/<workbookView[^>]*>/, '<workbookView/>')
|
34
35
|
got_xml_str.gsub!(/<calcPr[^>]*>/, '<calcPr/>')
|
35
|
-
when /
|
36
|
+
when %r{xl/worksheets/sheet\d+.xml}
|
36
37
|
exp_xml_str.gsub!(/horizontalDpi="200" /, '')
|
37
38
|
exp_xml_str.gsub!(/verticalDpi="200" /, '')
|
38
39
|
exp_xml_str.gsub!(/(<pageSetup[^>]*) r:id="rId1"/, '\1')
|
39
|
-
when /
|
40
|
+
when %r{xl/charts/chart\d+.xml}
|
40
41
|
exp_xml_str.gsub!(/<c:pageMargins[^>]*>/, '<c:pageMargins/>')
|
41
42
|
got_xml_str.gsub!(/<c:pageMargins[^>]*>/, '<c:pageMargins/>')
|
42
43
|
end
|
43
44
|
|
45
|
+
got_xml = _xml_to_list(got_xml_str)
|
46
|
+
|
44
47
|
if exp_entry.name =~ /.vml\z/
|
45
|
-
got_xml = _xml_to_list(got_xml_str)
|
46
48
|
exp_xml = _vml_to_list(exp_xml_str)
|
47
49
|
else
|
48
|
-
got_xml = _xml_to_list(got_xml_str)
|
49
50
|
exp_xml = _xml_to_list(exp_xml_str)
|
50
51
|
end
|
51
52
|
|
@@ -70,29 +71,27 @@ module XlsxComparable
|
|
70
71
|
|
71
72
|
def _xml_to_list(xml_str)
|
72
73
|
xml_str.strip.split(/>\s*</).each do |el|
|
73
|
-
el.
|
74
|
+
el.delete!("\r")
|
74
75
|
el.insert 0, '<' unless el[0] == '<'
|
75
76
|
el << '>' unless el[-1] == '>'
|
76
77
|
end
|
77
78
|
end
|
78
79
|
|
79
80
|
def _vml_to_list(vml_str)
|
80
|
-
vml_str.
|
81
|
+
vml_str.delete!("\r")
|
81
82
|
|
82
83
|
vml = vml_str.split("\n")
|
83
|
-
vml_str = String.new
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
wml_str << line
|
95
|
-
end
|
84
|
+
vml_str = String.new
|
85
|
+
vml.each do |line|
|
86
|
+
line.strip!
|
87
|
+
next if line == ''
|
88
|
+
|
89
|
+
line.tr!(?', ?")
|
90
|
+
line << ' ' if line =~ /"$/
|
91
|
+
line << "\n" if line =~ />$/
|
92
|
+
line.gsub!('><', ">\n<")
|
93
|
+
line.strip! if line == "<x:Anchor>\n"
|
94
|
+
wml_str << line
|
96
95
|
end
|
97
96
|
vml_str.rstrip.split("\n")
|
98
97
|
end
|
data/test/test-errors.rb
CHANGED
@@ -1,21 +1,33 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'test/unit'
|
4
|
+
require 'support/with_xlsx_file'
|
4
5
|
|
5
6
|
class TestErrors < Test::Unit::TestCase
|
7
|
+
include WithXlsxFile
|
8
|
+
|
6
9
|
def test_long_sheet_name
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
assert_raise(RuntimeError.new('worksheet was not created')) do
|
10
|
+
with_xlsx_file('tmp/error_long_sheet_name.xlsx') do |wb|
|
11
|
+
was_in_block = false
|
12
|
+
assert_raise(XlsxWriter::Error.new('worksheet was not created')) do
|
11
13
|
wb.add_worksheet('a' * 32) do |ws|
|
12
14
|
was_in_block = true
|
13
15
|
ws.add_row(['test'])
|
14
16
|
end
|
15
17
|
end
|
18
|
+
assert_equal(was_in_block, false)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_written_rich_string
|
23
|
+
with_xlsx_file('tmp/error_written_rich_string.xlsx') do |wb|
|
24
|
+
ws = wb.add_worksheet
|
25
|
+
rs = XlsxWriter::RichString.new(wb, ['1'])
|
26
|
+
rs << ' 2'
|
27
|
+
ws.add_row([rs])
|
28
|
+
assert_raise(XlsxWriter::Error.new('Cannot modify as the RichString has already been written to a workbook.')) do
|
29
|
+
rs << ' 3'
|
30
|
+
end
|
16
31
|
end
|
17
|
-
assert_equal(was_in_block, false)
|
18
|
-
ensure
|
19
|
-
File.delete file_path if file_path && File.exist?(file_path)
|
20
32
|
end
|
21
33
|
end
|
data/test/test-escapes.rb
CHANGED
@@ -3,6 +3,17 @@
|
|
3
3
|
require_relative './xlsx-func-testcase'
|
4
4
|
|
5
5
|
class TestEscapes < XlsxWriterTestCase
|
6
|
+
test 'escapes03' do |wb|
|
7
|
+
wb
|
8
|
+
.add_format(:bold, bold: true)
|
9
|
+
.add_format(:italic, italic: true)
|
10
|
+
.add_worksheet
|
11
|
+
.write_string('A1', 'Foo', :bold)
|
12
|
+
.write_string('A2', 'Bar', :italic)
|
13
|
+
.write_rich_string('A3', [['a'], ["b\"<>'c", :bold], ['defg']])
|
14
|
+
|
15
|
+
end
|
16
|
+
|
6
17
|
test 'escapes04' do |wb|
|
7
18
|
wb.add_worksheet
|
8
19
|
.write_url(0, 'A', 'http://www.perl.com/?a=1&b=2')
|
data/test/test-optimize.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# coding: utf-8
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require_relative './xlsx-func-testcase'
|
@@ -18,12 +19,54 @@ class TestOptimize < XlsxWriterTestCase
|
|
18
19
|
# G1 should be ignored since a later row has already been written.
|
19
20
|
end
|
20
21
|
|
22
|
+
test('optimize04', constant_memory: true) do |wb|
|
23
|
+
wb
|
24
|
+
.add_format(:bold, bold: true)
|
25
|
+
.add_format(:italic, italic: true)
|
26
|
+
.add_worksheet
|
27
|
+
.write_string('A1', 'Foo', :bold)
|
28
|
+
.write_string('A2', 'Bar', :italic)
|
29
|
+
.write_rich_string('A3', ['a', ['bc', :bold], 'defg'])
|
30
|
+
end
|
31
|
+
|
32
|
+
test('optimize05', constant_memory: true) do |wb|
|
33
|
+
t1, t2, t3, t4 = [
|
34
|
+
['a', ['bc', :bold], 'defg'],
|
35
|
+
['a', ['bcdef', :bold], 'g'],
|
36
|
+
['abc', ['de', :italic], 'fg'],
|
37
|
+
[['abcd', :italic], ['efg', nil]],
|
38
|
+
].map { |parts| XlsxWriter::RichString.new(wb, parts) }
|
39
|
+
wb
|
40
|
+
.add_format(:bold, bold: true)
|
41
|
+
.add_format(:italic, italic: true)
|
42
|
+
.add_worksheet
|
43
|
+
.write_string('A1', 'Foo', :bold)
|
44
|
+
.write_string('A2', 'Bar', :italic)
|
45
|
+
.write_rich_string('A3', t1)
|
46
|
+
.write_rich_string('B4', t3)
|
47
|
+
.write_rich_string('C5', t1)
|
48
|
+
.write_rich_string('D6', t3)
|
49
|
+
.write_rich_string('E7', t2)
|
50
|
+
.write_rich_string('F8', t4)
|
51
|
+
end
|
52
|
+
|
21
53
|
test('optimize06', constant_memory: true) do |wb|
|
22
54
|
ws = wb.add_worksheet
|
23
55
|
ws.write_string(0, 0, '_x0000_', nil)
|
24
56
|
(1..127).each { |i| ws.write_string(i, 0, i.chr, nil) unless i == 34 }
|
25
57
|
end
|
26
58
|
|
59
|
+
|
60
|
+
test('optimize08', constant_memory: true) do |wb|
|
61
|
+
wb
|
62
|
+
.add_format(:bold, bold: true)
|
63
|
+
.add_format(:italic, italic: true)
|
64
|
+
.add_worksheet
|
65
|
+
.write_string('A1', 'Foo', :bold)
|
66
|
+
.write_string('A2', 'Bar', :italic)
|
67
|
+
.write_rich_string('A3', [' a', ['bc', :bold], 'defg '])
|
68
|
+
end
|
69
|
+
|
27
70
|
test('optimize21', constant_memory: true) do |wb|
|
28
71
|
wb.add_worksheet
|
29
72
|
.write_string(0, 'A', 'Foo', nil)
|
@@ -0,0 +1,159 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative './xlsx-func-testcase'
|
5
|
+
|
6
|
+
class TestRichString < XlsxWriterTestCase
|
7
|
+
test('rich_string01') do |wb|
|
8
|
+
wb
|
9
|
+
.add_format(:bold, bold: true)
|
10
|
+
.add_format(:italic, italic: true)
|
11
|
+
.add_worksheet
|
12
|
+
.write_string('A1', 'Foo', :bold)
|
13
|
+
.write_string('A2', 'Bar', :italic)
|
14
|
+
.write_rich_string('A3', ['a', ['bc', :bold], 'defg'])
|
15
|
+
end
|
16
|
+
|
17
|
+
test('rich_string02') do |wb|
|
18
|
+
wb
|
19
|
+
.add_format(:bold, bold: true)
|
20
|
+
.add_format(:italic, italic: true)
|
21
|
+
.add_worksheet
|
22
|
+
.write_string('A1', 'Foo', :bold)
|
23
|
+
.write_string('A2', 'Bar', :italic)
|
24
|
+
.write_rich_string('A3', ['abcd', ['ef', :italic], 'g'])
|
25
|
+
end
|
26
|
+
|
27
|
+
test('rich_string03') do |wb|
|
28
|
+
wb
|
29
|
+
.add_format(:bold, bold: true)
|
30
|
+
.add_format(:italic, italic: true)
|
31
|
+
.add_worksheet
|
32
|
+
.write_string('A1', 'Foo', :bold)
|
33
|
+
.write_string('A2', 'Bar', :italic)
|
34
|
+
.write_rich_string('A3', [['abc', :bold], 'defg'])
|
35
|
+
end
|
36
|
+
|
37
|
+
test('rich_string04') do |wb|
|
38
|
+
wb
|
39
|
+
.add_format(:bold, bold: true)
|
40
|
+
.add_format(:italic, italic: true)
|
41
|
+
.add_worksheet
|
42
|
+
.write_string('A1', 'Foo', :bold)
|
43
|
+
.write_string('A2', 'Bar', :italic)
|
44
|
+
.write_rich_string('A3', [['abc', :bold], ['defg', :italic]])
|
45
|
+
end
|
46
|
+
|
47
|
+
test('rich_string05') do |wb|
|
48
|
+
wb
|
49
|
+
.add_format(:bold, bold: true)
|
50
|
+
.add_format(:italic, italic: true)
|
51
|
+
.add_worksheet
|
52
|
+
.set_column('A', 'A', width: 30)
|
53
|
+
.write_string('A1', 'Foo', :bold)
|
54
|
+
.write_string('A2', 'Bar', :italic)
|
55
|
+
.write_rich_string('A3',
|
56
|
+
XlsxWriter::RichString.new(wb) <<
|
57
|
+
'This is ' << ['bold', :bold] << ' and this is ' << ['italic', :italic]
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
test('rich_string06') do |wb|
|
63
|
+
wb
|
64
|
+
.add_format(:red, font_color: XlsxWriter::Format::COLOR_RED)
|
65
|
+
.add_worksheet
|
66
|
+
.write_string('A1', 'Foo', :red)
|
67
|
+
.write_string('A2', 'Bar')
|
68
|
+
.write_rich_string('A3', ['ab', ['cde', :red], 'fg'])
|
69
|
+
end
|
70
|
+
|
71
|
+
test('rich_string07') do |wb|
|
72
|
+
t1, t2, t3, t4 = [
|
73
|
+
['a', ['bc', :bold], 'defg'],
|
74
|
+
['a', ['bcdef', :bold], 'g'],
|
75
|
+
['abc', ['de', :italic], 'fg'],
|
76
|
+
[['abcd', :italic], ['efg', nil]],
|
77
|
+
].map { |parts| XlsxWriter::RichString.new(wb, parts) }
|
78
|
+
wb
|
79
|
+
.add_format(:bold, bold: true)
|
80
|
+
.add_format(:italic, italic: true)
|
81
|
+
.add_worksheet
|
82
|
+
.write_string('A1', 'Foo', :bold)
|
83
|
+
.write_string('A2', 'Bar', :italic)
|
84
|
+
.write_rich_string('A3', t1)
|
85
|
+
.write_rich_string('B4', t3)
|
86
|
+
.write_rich_string('C5', t1)
|
87
|
+
.write_rich_string('D6', t3)
|
88
|
+
.write_rich_string('E7', t2)
|
89
|
+
.write_rich_string('F8', t4)
|
90
|
+
end
|
91
|
+
|
92
|
+
test('rich_string08') do |wb|
|
93
|
+
wb
|
94
|
+
.add_format(:bold, bold: true)
|
95
|
+
.add_format(:italic, italic: true)
|
96
|
+
.add_format(:centered, align: XlsxWriter::Format::ALIGN_CENTER)
|
97
|
+
.add_worksheet
|
98
|
+
.write_string('A1', 'Foo', :bold)
|
99
|
+
.write_string('A2', 'Bar', :italic)
|
100
|
+
.write_rich_string('A3', ['ab', ['cd', :bold], 'efg'], :centered)
|
101
|
+
end
|
102
|
+
|
103
|
+
test('rich_string09') do |wb|
|
104
|
+
wb
|
105
|
+
.add_format(:bold, bold: true)
|
106
|
+
.add_format(:italic, italic: true)
|
107
|
+
ws = wb.add_worksheet
|
108
|
+
ws
|
109
|
+
.write_string('A1', 'Foo', :bold)
|
110
|
+
.write_string('A2', 'Bar', :italic)
|
111
|
+
.write_rich_string('A3', ['a', ['bc', :bold], 'defg'])
|
112
|
+
|
113
|
+
assert_raise(XlsxWriter::Error, 'Function parameter validation error.') do
|
114
|
+
ws.write_rich_string('A3', ['', ['bc', :bold], 'defg'])
|
115
|
+
end
|
116
|
+
assert_raise(XlsxWriter::Error, 'Function parameter validation error.') do
|
117
|
+
ws.write_rich_string('A3', [])
|
118
|
+
end
|
119
|
+
assert_raise(XlsxWriter::Error, 'Function parameter validation error.') do
|
120
|
+
ws.write_rich_string('A3', [['foo', :bold]])
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
test('rich_string10') do |wb|
|
125
|
+
wb
|
126
|
+
.add_format(:bold, bold: true)
|
127
|
+
.add_format(:italic, italic: true)
|
128
|
+
.add_worksheet
|
129
|
+
.write_string('A1', 'Foo', :bold)
|
130
|
+
.write_string('A2', 'Bar', :italic)
|
131
|
+
.write_rich_string('A3', [' a', ['bc', :bold], 'defg '])
|
132
|
+
end
|
133
|
+
|
134
|
+
test('rich_string11') do |wb|
|
135
|
+
wb
|
136
|
+
.add_format(:bold, bold: true)
|
137
|
+
.add_format(:italic, italic: true)
|
138
|
+
.add_worksheet
|
139
|
+
.write_string('A1', 'Foo', :bold)
|
140
|
+
.write_string('A2', 'Bar', :italic)
|
141
|
+
.write_rich_string('A3', ['a', ['☺', :bold], 'defg'])
|
142
|
+
end
|
143
|
+
|
144
|
+
test('rich_string12') do |wb|
|
145
|
+
wb
|
146
|
+
.add_format(:bold, bold: true)
|
147
|
+
.add_format(:italic, italic: true)
|
148
|
+
.add_format(:wrap, text_wrap: true)
|
149
|
+
.add_worksheet
|
150
|
+
.set_column('A', 'A', width: 30)
|
151
|
+
.set_row(2, height: 60)
|
152
|
+
.write_string('A1', 'Foo', :bold)
|
153
|
+
.write_string('A2', 'Bar', :italic)
|
154
|
+
.write_rich_string('A3', XlsxWriter::RichString.new(wb) <<
|
155
|
+
"This is\n" << ["bold\n", :bold] << "and this is\n" << ['italic', :italic],
|
156
|
+
:wrap
|
157
|
+
)
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './support/with_xlsx_file'
|
4
|
+
|
5
|
+
class TestRubyWorksheet < Test::Unit::TestCase
|
6
|
+
include WithXlsxFile
|
7
|
+
|
8
|
+
def test_auto_width
|
9
|
+
with_xlsx_file do |wb|
|
10
|
+
ws = wb.add_worksheet
|
11
|
+
|
12
|
+
ws.add_row ['asd', 'asdf', 'asdfg', 'asdfgh', 'asdfghj', 'd'*250]
|
13
|
+
assert_in_epsilon(4.4, ws.get_column_auto_width('A'))
|
14
|
+
assert_in_epsilon(4.4, ws.get_column_auto_width('B'))
|
15
|
+
assert_in_epsilon(5.5, ws.get_column_auto_width('C'))
|
16
|
+
assert_in_epsilon(6.6, ws.get_column_auto_width('D'))
|
17
|
+
assert_in_epsilon(6.6, ws.get_column_auto_width('E'))
|
18
|
+
assert_in_epsilon(255, ws.get_column_auto_width('F'))
|
19
|
+
|
20
|
+
wb.add_format :f, font_size: 14
|
21
|
+
ws.add_row ['asd', 'asdf', 'asdfg', 'asdfgh', 'asdfghj'], style: :f
|
22
|
+
assert_in_epsilon(5.6, ws.get_column_auto_width('A'))
|
23
|
+
assert_in_epsilon(5.6, ws.get_column_auto_width('B'))
|
24
|
+
assert_in_epsilon(7.0, ws.get_column_auto_width('C'))
|
25
|
+
assert_in_epsilon(8.4, ws.get_column_auto_width('D'))
|
26
|
+
assert_in_epsilon(8.4, ws.get_column_auto_width('E'))
|
27
|
+
|
28
|
+
assert_raise(XlsxWriter::Error.new('Function parameter validation error.')) do
|
29
|
+
ws.write_rich_string('A2', [])
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/test/xlsx-func-testcase.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'xlsxwriter'
|
4
4
|
require_relative './support/xlsx_comparable'
|
5
|
+
require_relative './support/with_xlsx_file'
|
5
6
|
|
6
7
|
class XlsxWriterTestCaseConfig
|
7
8
|
attr_accessor :ignore_elements, :ignore_files
|
@@ -12,23 +13,22 @@ class XlsxWriterTestCaseConfig
|
|
12
13
|
end
|
13
14
|
|
14
15
|
class XlsxWriterTestCase < Test::Unit::TestCase
|
16
|
+
include WithXlsxFile
|
15
17
|
include XlsxComparable
|
16
18
|
|
17
|
-
def self.test(name, opts
|
19
|
+
def self.test(name, **opts, &block)
|
18
20
|
define_method(:"test_#{name}") do
|
19
21
|
file_path = "tmp/#{name}.xlsx"
|
20
22
|
ref_name = opts && opts.delete(:ref_file_name) || name
|
21
23
|
ref_file_path = "ext/xlsxwriter/libxlsxwriter/test/functional/xlsx_files/#{ref_name}.xlsx"
|
22
|
-
|
23
|
-
tc = XlsxWriterTestCaseConfig.new
|
24
|
-
args = [file_path, opts].compact
|
25
|
-
XlsxWriter::Workbook.open(*args) do |wb|
|
26
|
-
instance_exec(wb, tc, &block)
|
27
|
-
end
|
24
|
+
tc = XlsxWriterTestCaseConfig.new
|
28
25
|
|
26
|
+
compare_files = proc {
|
29
27
|
assert_xlsx_equal file_path, ref_file_path, tc.ignore_files, tc.ignore_elements
|
30
|
-
|
31
|
-
|
28
|
+
}
|
29
|
+
|
30
|
+
with_xlsx_file(file_path, **opts, after: compare_files) do |wb|
|
31
|
+
instance_exec(wb, tc, &block)
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xlsxwriter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.0.pre
|
4
|
+
version: 0.2.0.pre.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick H
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-04-
|
11
|
+
date: 2019-04-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -25,33 +25,33 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: rubyzip
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '1.2'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '1.2'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: test-unit
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '3.2'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '3.2'
|
55
55
|
description:
|
56
56
|
email:
|
57
57
|
executables: []
|
@@ -129,6 +129,8 @@ files:
|
|
129
129
|
- ext/xlsxwriter/libxlsxwriter/third_party/tmpfileplus/Makefile
|
130
130
|
- ext/xlsxwriter/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.c
|
131
131
|
- ext/xlsxwriter/libxlsxwriter/third_party/tmpfileplus/tmpfileplus.h
|
132
|
+
- ext/xlsxwriter/rich_string.c
|
133
|
+
- ext/xlsxwriter/rich_string.h
|
132
134
|
- ext/xlsxwriter/workbook.c
|
133
135
|
- ext/xlsxwriter/workbook.h
|
134
136
|
- ext/xlsxwriter/workbook_properties.c
|
@@ -138,9 +140,12 @@ files:
|
|
138
140
|
- ext/xlsxwriter/xlsxwriter.c
|
139
141
|
- ext/xlsxwriter/xlsxwriter_ext.h
|
140
142
|
- lib/xlsxwriter.rb
|
143
|
+
- lib/xlsxwriter/error.rb
|
144
|
+
- lib/xlsxwriter/rich_string.rb
|
141
145
|
- lib/xlsxwriter/version.rb
|
142
146
|
- lib/xlsxwriter/worksheet.rb
|
143
147
|
- test/run-test.rb
|
148
|
+
- test/support/with_xlsx_file.rb
|
144
149
|
- test/support/xlsx_comparable.rb
|
145
150
|
- test/test-array-formula.rb
|
146
151
|
- test/test-autofilter.rb
|
@@ -177,7 +182,9 @@ files:
|
|
177
182
|
- test/test-properties.rb
|
178
183
|
- test/test-protect.rb
|
179
184
|
- test/test-repeat.rb
|
185
|
+
- test/test-rich-string.rb
|
180
186
|
- test/test-row-col-format.rb
|
187
|
+
- test/test-ruby-worksheet.rb
|
181
188
|
- test/test-set-selection.rb
|
182
189
|
- test/test-set-start-page.rb
|
183
190
|
- test/test-simple.rb
|
@@ -212,6 +219,7 @@ test_files:
|
|
212
219
|
- test/test-page-setup.rb
|
213
220
|
- test/test-page-breaks.rb
|
214
221
|
- test/test-protect.rb
|
222
|
+
- test/test-ruby-worksheet.rb
|
215
223
|
- test/test-chart-axis.rb
|
216
224
|
- test/test-print-area.rb
|
217
225
|
- test/test-default-row.rb
|
@@ -228,6 +236,7 @@ test_files:
|
|
228
236
|
- test/test-row-col-format.rb
|
229
237
|
- test/test-escapes.rb
|
230
238
|
- test/test-formatting.rb
|
239
|
+
- test/support/with_xlsx_file.rb
|
231
240
|
- test/support/xlsx_comparable.rb
|
232
241
|
- test/test-image.rb
|
233
242
|
- test/test-gridlines.rb
|
@@ -241,6 +250,7 @@ test_files:
|
|
241
250
|
- test/test-print-options.rb
|
242
251
|
- test/test-optimize.rb
|
243
252
|
- test/test-print-scale.rb
|
253
|
+
- test/test-rich-string.rb
|
244
254
|
- test/test-chart-scatter.rb
|
245
255
|
- test/test-misc.rb
|
246
256
|
- test/test-autofilter.rb
|