xlsxwriter 0.2.0.pre → 0.2.0.pre.2
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.
- 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
|