write_xlsx 1.09.5 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/Changes +5 -0
  4. data/LICENSE.txt +1 -1
  5. data/examples/autofilter.rb +38 -9
  6. data/examples/dynamic_arrays.rb +247 -0
  7. data/examples/lambda.rb +43 -0
  8. data/examples/watermark.png +0 -0
  9. data/examples/watermark.rb +26 -0
  10. data/lib/write_xlsx/chart.rb +1 -0
  11. data/lib/write_xlsx/chartsheet.rb +1 -0
  12. data/lib/write_xlsx/col_name.rb +1 -0
  13. data/lib/write_xlsx/colors.rb +1 -0
  14. data/lib/write_xlsx/compatibility.rb +1 -0
  15. data/lib/write_xlsx/drawing.rb +20 -10
  16. data/lib/write_xlsx/format.rb +5 -0
  17. data/lib/write_xlsx/formats.rb +1 -0
  18. data/lib/write_xlsx/gradient.rb +2 -0
  19. data/lib/write_xlsx/package/app.rb +1 -0
  20. data/lib/write_xlsx/package/button.rb +6 -2
  21. data/lib/write_xlsx/package/comments.rb +3 -1
  22. data/lib/write_xlsx/package/conditional_format.rb +1 -0
  23. data/lib/write_xlsx/package/content_types.rb +1 -0
  24. data/lib/write_xlsx/package/core.rb +1 -0
  25. data/lib/write_xlsx/package/custom.rb +1 -0
  26. data/lib/write_xlsx/package/metadata.rb +1 -0
  27. data/lib/write_xlsx/package/packager.rb +1 -0
  28. data/lib/write_xlsx/package/relationships.rb +1 -0
  29. data/lib/write_xlsx/package/shared_strings.rb +1 -1
  30. data/lib/write_xlsx/package/styles.rb +1 -0
  31. data/lib/write_xlsx/package/table.rb +1 -0
  32. data/lib/write_xlsx/package/theme.rb +1 -0
  33. data/lib/write_xlsx/package/vml.rb +1 -0
  34. data/lib/write_xlsx/package/xml_writer_simple.rb +21 -2
  35. data/lib/write_xlsx/shape.rb +1 -0
  36. data/lib/write_xlsx/sheets.rb +1 -0
  37. data/lib/write_xlsx/sparkline.rb +1 -0
  38. data/lib/write_xlsx/utility.rb +2 -3
  39. data/lib/write_xlsx/version.rb +3 -1
  40. data/lib/write_xlsx/worksheet/cell_data.rb +52 -62
  41. data/lib/write_xlsx/worksheet/data_validation.rb +1 -0
  42. data/lib/write_xlsx/worksheet/hyperlink.rb +3 -2
  43. data/lib/write_xlsx/worksheet/page_setup.rb +1 -0
  44. data/lib/write_xlsx/worksheet.rb +260 -47
  45. data/lib/write_xlsx/zip_file_utils.rb +1 -0
  46. data/lib/write_xlsx.rb +1 -0
  47. data/write_xlsx.gemspec +1 -0
  48. metadata +8 -4
@@ -44,7 +44,7 @@ module Writexlsx
44
44
  @index = index
45
45
  @name = name
46
46
  @colinfo = {}
47
- @cell_data_table = {}
47
+ @cell_data_table = []
48
48
  @excel_version = 2007
49
49
  @palette = workbook.palette
50
50
  @default_url_format = workbook.default_url_format
@@ -61,6 +61,7 @@ module Writexlsx
61
61
  @selections = []
62
62
  @panes = []
63
63
  @hide_row_col_headers = 0
64
+ @top_left_cell = ''
64
65
 
65
66
  @tab_color = 0
66
67
 
@@ -103,6 +104,9 @@ module Writexlsx
103
104
  @vml_drawing_rels = {}
104
105
  @vml_drawing_rels_id = 0
105
106
  @has_dynamic_arrays = false
107
+
108
+ @use_future_functions = false
109
+
106
110
  @header_images = []
107
111
  @footer_images = []
108
112
  @background_image = ''
@@ -256,8 +260,8 @@ module Writexlsx
256
260
  if range.nil?
257
261
  raise "The range must be defined in unprotect_range())\n"
258
262
  else
259
- range.gsub!(/\$/, "")
260
- range.sub!(/^=/, "")
263
+ range = range.gsub(/\$/, "")
264
+ range = range.sub(/^=/, "")
261
265
  @num_protected_ranges += 1
262
266
  end
263
267
 
@@ -410,6 +414,18 @@ module Writexlsx
410
414
  @selections = [[nil, active_cell, sqref]]
411
415
  end
412
416
 
417
+ ###############################################################################
418
+ #
419
+ # set_top_left_cell()
420
+ #
421
+ # Set the first visible cell at the top left of the worksheet.
422
+ #
423
+ def set_top_left_cell(*args)
424
+ row, col = row_col_notation(args)
425
+
426
+ @top_left_cell = xl_rowcol_to_cell(row, col)
427
+ end
428
+
413
429
  #
414
430
  # :call-seq:
415
431
  # freeze_panes(row, col [ , top_row, left_col ] )
@@ -813,7 +829,8 @@ module Writexlsx
813
829
  # Set the option to print the worksheet in black and white.
814
830
  #
815
831
  def print_black_and_white
816
- @page_setup.black_white = true
832
+ @page_setup.black_white = true
833
+ @page_setup.page_setup_changed = true
817
834
  end
818
835
 
819
836
  #
@@ -878,8 +895,11 @@ module Writexlsx
878
895
  token = row_col_args[2] || ''
879
896
  token = token.to_s if token.instance_of?(Time)
880
897
 
898
+ fmt = row_col_args[3]
899
+ if fmt.respond_to?(:force_text_format?) && fmt.force_text_format?
900
+ write_string(*args) # Force text format
881
901
  # Match an array ref.
882
- if token.respond_to?(:to_ary)
902
+ elsif token.respond_to?(:to_ary)
883
903
  write_row(*args)
884
904
  elsif token.respond_to?(:coerce) # Numeric
885
905
  write_number(*args)
@@ -918,7 +938,7 @@ module Writexlsx
918
938
 
919
939
  #
920
940
  # :call-seq:
921
- # write_row(row, col, array [ , format ] )
941
+ # write_row(row, col, array [ , format ])
922
942
  #
923
943
  # Write a row of data starting from (row, col). Call write_col() if any of
924
944
  # the elements of the array are in turn array. This allows the writing
@@ -942,7 +962,7 @@ module Writexlsx
942
962
 
943
963
  #
944
964
  # :call-seq:
945
- # write_col(row, col, array [ , format ] )
965
+ # write_col(row, col, array [ , format ])
946
966
  #
947
967
  # Write a column of data starting from (row, col). Call write_row() if any of
948
968
  # the elements of the array are in turn array. This allows the writing
@@ -981,7 +1001,7 @@ module Writexlsx
981
1001
 
982
1002
  #
983
1003
  # :call-seq:
984
- # write_number(row, column, number [ , format ] )
1004
+ # write_number(row, column, number [ , format ])
985
1005
  #
986
1006
  # Write an integer or a float to the cell specified by row and column:
987
1007
  #
@@ -994,12 +1014,12 @@ module Writexlsx
994
1014
  check_dimensions(row, col)
995
1015
  store_row_col_max_min_values(row, col)
996
1016
 
997
- store_data_to_table(NumberCellData.new(self, row, col, num, xf))
1017
+ store_data_to_table(NumberCellData.new(num, xf), row, col)
998
1018
  end
999
1019
 
1000
1020
  #
1001
1021
  # :call-seq:
1002
- # write_string(row, column, string [, format ] )
1022
+ # write_string(row, column, string [, format ])
1003
1023
  #
1004
1024
  # Write a string to the specified row and column (zero indexed).
1005
1025
  # +format+ is optional.
@@ -1016,12 +1036,12 @@ module Writexlsx
1016
1036
 
1017
1037
  index = shared_string_index(str.length > STR_MAX ? str[0, STR_MAX] : str)
1018
1038
 
1019
- store_data_to_table(StringCellData.new(self, row, col, index, xf))
1039
+ store_data_to_table(StringCellData.new(index, xf), row, col)
1020
1040
  end
1021
1041
 
1022
1042
  #
1023
1043
  # :call-seq:
1024
- # write_rich_string(row, column, (string | format, string)+, [,cell_format] )
1044
+ # write_rich_string(row, column, (string | format, string)+, [,cell_format])
1025
1045
  #
1026
1046
  # The write_rich_string() method is used to write strings with multiple formats.
1027
1047
  # The method receives string fragments prefixed by format objects. The final
@@ -1044,7 +1064,7 @@ module Writexlsx
1044
1064
 
1045
1065
  index = shared_string_index(xml_str_of_rich_string(fragments))
1046
1066
 
1047
- store_data_to_table(StringCellData.new(self, row, col, index, xf))
1067
+ store_data_to_table(StringCellData.new(index, xf), row, col)
1048
1068
  end
1049
1069
 
1050
1070
  #
@@ -1067,12 +1087,177 @@ module Writexlsx
1067
1087
  check_dimensions(row, col)
1068
1088
  store_row_col_max_min_values(row, col)
1069
1089
 
1070
- store_data_to_table(BlankCellData.new(self, row, col, xf))
1090
+ store_data_to_table(BlankCellData.new(xf), row, col)
1071
1091
  end
1072
1092
 
1093
+ def expand_formula(formula, function, addition = '')
1094
+ if formula =~ /\b(#{function})/
1095
+ formula.gsub(
1096
+ ::Regexp.last_match(1),
1097
+ "_xlfn#{addition}.#{::Regexp.last_match(1)}"
1098
+ )
1099
+ else
1100
+ formula
1101
+ end
1102
+ end
1103
+ private :expand_formula
1104
+
1105
+ #
1106
+ # Utility method to strip equal sign and array braces from a formula
1107
+ # and also expand out future and dynamic array formulas.
1108
+ #
1109
+ def prepare_formula(given_formula)
1110
+ # Ignore empty/null formulas.
1111
+ return given_formula unless ptrue?(given_formula)
1112
+
1113
+ # Remove array formula braces and the leading =.
1114
+ formula = given_formula.sub(/^\{(.*)\}$/, '\1').sub(/^=/, '')
1115
+
1116
+ # # Don't expand formulas that the user has already expanded.
1117
+ return formula if formula =~ /_xlfn\./
1118
+
1119
+ # Expand dynamic array formulas.
1120
+ formula = expand_formula(formula, 'LET\(')
1121
+ formula = expand_formula(formula, 'LAMBDA\(')
1122
+ formula = expand_formula(formula, 'SINGLE\(')
1123
+ formula = expand_formula(formula, 'SORTBY\(')
1124
+ formula = expand_formula(formula, 'UNIQUE\(')
1125
+ formula = expand_formula(formula, 'XMATCH\(')
1126
+ formula = expand_formula(formula, 'XLOOKUP\(')
1127
+ formula = expand_formula(formula, 'SEQUENCE\(')
1128
+ formula = expand_formula(formula, 'RANDARRAY\(')
1129
+ formula = expand_formula(formula, 'SORT\(', '._xlws')
1130
+ formula = expand_formula(formula, 'ANCHORARRAY\(')
1131
+ formula = expand_formula(formula, 'FILTER\(', '._xlws')
1132
+
1133
+ return formula unless @use_future_functions
1134
+
1135
+ # Future functions.
1136
+ formula = expand_formula(formula, 'ACOTH\(')
1137
+ formula = expand_formula(formula, 'ACOT\(')
1138
+ formula = expand_formula(formula, 'AGGREGATE\(')
1139
+ formula = expand_formula(formula, 'ARABIC\(')
1140
+ formula = expand_formula(formula, 'BASE\(')
1141
+ formula = expand_formula(formula, 'BETA.DIST\(')
1142
+ formula = expand_formula(formula, 'BETA.INV\(')
1143
+ formula = expand_formula(formula, 'BINOM.DIST.RANGE\(')
1144
+ formula = expand_formula(formula, 'BINOM.DIST\(')
1145
+ formula = expand_formula(formula, 'BINOM.INV\(')
1146
+ formula = expand_formula(formula, 'BITAND\(')
1147
+ formula = expand_formula(formula, 'BITLSHIFT\(')
1148
+ formula = expand_formula(formula, 'BITOR\(')
1149
+ formula = expand_formula(formula, 'BITRSHIFT\(')
1150
+ formula = expand_formula(formula, 'BITXOR\(')
1151
+ formula = expand_formula(formula, 'CEILING.MATH\(')
1152
+ formula = expand_formula(formula, 'CEILING.PRECISE\(')
1153
+ formula = expand_formula(formula, 'CHISQ.DIST.RT\(')
1154
+ formula = expand_formula(formula, 'CHISQ.DIST\(')
1155
+ formula = expand_formula(formula, 'CHISQ.INV.RT\(')
1156
+ formula = expand_formula(formula, 'CHISQ.INV\(')
1157
+ formula = expand_formula(formula, 'CHISQ.TEST\(')
1158
+ formula = expand_formula(formula, 'COMBINA\(')
1159
+ formula = expand_formula(formula, 'CONCAT\(')
1160
+ formula = expand_formula(formula, 'CONFIDENCE.NORM\(')
1161
+ formula = expand_formula(formula, 'CONFIDENCE.T\(')
1162
+ formula = expand_formula(formula, 'COTH\(')
1163
+ formula = expand_formula(formula, 'COT\(')
1164
+ formula = expand_formula(formula, 'COVARIANCE.P\(')
1165
+ formula = expand_formula(formula, 'COVARIANCE.S\(')
1166
+ formula = expand_formula(formula, 'CSCH\(')
1167
+ formula = expand_formula(formula, 'CSC\(')
1168
+ formula = expand_formula(formula, 'DAYS\(')
1169
+ formula = expand_formula(formula, 'DECIMAL\(')
1170
+ formula = expand_formula(formula, 'ERF.PRECISE\(')
1171
+ formula = expand_formula(formula, 'ERFC.PRECISE\(')
1172
+ formula = expand_formula(formula, 'EXPON.DIST\(')
1173
+ formula = expand_formula(formula, 'F.DIST.RT\(')
1174
+ formula = expand_formula(formula, 'F.DIST\(')
1175
+ formula = expand_formula(formula, 'F.INV.RT\(')
1176
+ formula = expand_formula(formula, 'F.INV\(')
1177
+ formula = expand_formula(formula, 'F.TEST\(')
1178
+ formula = expand_formula(formula, 'FILTERXML\(')
1179
+ formula = expand_formula(formula, 'FLOOR.MATH\(')
1180
+ formula = expand_formula(formula, 'FLOOR.PRECISE\(')
1181
+ formula = expand_formula(formula, 'FORECAST.ETS.CONFINT\(')
1182
+ formula = expand_formula(formula, 'FORECAST.ETS.SEASONALITY\(')
1183
+ formula = expand_formula(formula, 'FORECAST.ETS.STAT\(')
1184
+ formula = expand_formula(formula, 'FORECAST.ETS\(')
1185
+ formula = expand_formula(formula, 'FORECAST.LINEAR\(')
1186
+ formula = expand_formula(formula, 'FORMULATEXT\(')
1187
+ formula = expand_formula(formula, 'GAMMA.DIST\(')
1188
+ formula = expand_formula(formula, 'GAMMA.INV\(')
1189
+ formula = expand_formula(formula, 'GAMMALN.PRECISE\(')
1190
+ formula = expand_formula(formula, 'GAMMA\(')
1191
+ formula = expand_formula(formula, 'GAUSS\(')
1192
+ formula = expand_formula(formula, 'HYPGEOM.DIST\(')
1193
+ formula = expand_formula(formula, 'IFNA\(')
1194
+ formula = expand_formula(formula, 'IFS\(')
1195
+ formula = expand_formula(formula, 'IMCOSH\(')
1196
+ formula = expand_formula(formula, 'IMCOT\(')
1197
+ formula = expand_formula(formula, 'IMCSCH\(')
1198
+ formula = expand_formula(formula, 'IMCSC\(')
1199
+ formula = expand_formula(formula, 'IMSECH\(')
1200
+ formula = expand_formula(formula, 'IMSEC\(')
1201
+ formula = expand_formula(formula, 'IMSINH\(')
1202
+ formula = expand_formula(formula, 'IMTAN\(')
1203
+ formula = expand_formula(formula, 'ISFORMULA\(')
1204
+ formula = expand_formula(formula, 'ISOWEEKNUM\(')
1205
+ formula = expand_formula(formula, 'LOGNORM.DIST\(')
1206
+ formula = expand_formula(formula, 'LOGNORM.INV\(')
1207
+ formula = expand_formula(formula, 'MAXIFS\(')
1208
+ formula = expand_formula(formula, 'MINIFS\(')
1209
+ formula = expand_formula(formula, 'MODE.MULT\(')
1210
+ formula = expand_formula(formula, 'MODE.SNGL\(')
1211
+ formula = expand_formula(formula, 'MUNIT\(')
1212
+ formula = expand_formula(formula, 'NEGBINOM.DIST\(')
1213
+ formula = expand_formula(formula, 'NORM.DIST\(')
1214
+ formula = expand_formula(formula, 'NORM.INV\(')
1215
+ formula = expand_formula(formula, 'NORM.S.DIST\(')
1216
+ formula = expand_formula(formula, 'NORM.S.INV\(')
1217
+ formula = expand_formula(formula, 'NUMBERVALUE\(')
1218
+ formula = expand_formula(formula, 'PDURATION\(')
1219
+ formula = expand_formula(formula, 'PERCENTILE.EXC\(')
1220
+ formula = expand_formula(formula, 'PERCENTILE.INC\(')
1221
+ formula = expand_formula(formula, 'PERCENTRANK.EXC\(')
1222
+ formula = expand_formula(formula, 'PERCENTRANK.INC\(')
1223
+ formula = expand_formula(formula, 'PERMUTATIONA\(')
1224
+ formula = expand_formula(formula, 'PHI\(')
1225
+ formula = expand_formula(formula, 'POISSON.DIST\(')
1226
+ formula = expand_formula(formula, 'QUARTILE.EXC\(')
1227
+ formula = expand_formula(formula, 'QUARTILE.INC\(')
1228
+ formula = expand_formula(formula, 'QUERYSTRING\(')
1229
+ formula = expand_formula(formula, 'RANK.AVG\(')
1230
+ formula = expand_formula(formula, 'RANK.EQ\(')
1231
+ formula = expand_formula(formula, 'RRI\(')
1232
+ formula = expand_formula(formula, 'SECH\(')
1233
+ formula = expand_formula(formula, 'SEC\(')
1234
+ formula = expand_formula(formula, 'SHEETS\(')
1235
+ formula = expand_formula(formula, 'SHEET\(')
1236
+ formula = expand_formula(formula, 'SKEW.P\(')
1237
+ formula = expand_formula(formula, 'STDEV.P\(')
1238
+ formula = expand_formula(formula, 'STDEV.S\(')
1239
+ formula = expand_formula(formula, 'SWITCH\(')
1240
+ formula = expand_formula(formula, 'T.DIST.2T\(')
1241
+ formula = expand_formula(formula, 'T.DIST.RT\(')
1242
+ formula = expand_formula(formula, 'T.DIST\(')
1243
+ formula = expand_formula(formula, 'T.INV.2T\(')
1244
+ formula = expand_formula(formula, 'T.INV\(')
1245
+ formula = expand_formula(formula, 'T.TEST\(')
1246
+ formula = expand_formula(formula, 'TEXTJOIN\(')
1247
+ formula = expand_formula(formula, 'UNICHAR\(')
1248
+ formula = expand_formula(formula, 'UNICODE\(')
1249
+ formula = expand_formula(formula, 'VAR.P\(')
1250
+ formula = expand_formula(formula, 'VAR.S\(')
1251
+ formula = expand_formula(formula, 'WEBSERVICE\(')
1252
+ formula = expand_formula(formula, 'WEIBULL.DIST\(')
1253
+ formula = expand_formula(formula, 'XOR\(')
1254
+ expand_formula(formula, 'Z.TEST\(')
1255
+ end
1256
+ private :prepare_formula
1257
+
1073
1258
  #
1074
1259
  # :call-seq:
1075
- # write_formula(row, column, formula [ , format [ , value ] ] )
1260
+ # write_formula(row, column, formula [ , format [ , value ] ])
1076
1261
  #
1077
1262
  # Write a formula or function to the cell specified by +row+ and +column+:
1078
1263
  #
@@ -1081,6 +1266,15 @@ module Writexlsx
1081
1266
  row, col, formula, format, value = row_col_notation(args)
1082
1267
  raise WriteXLSXInsufficientArgumentError if [row, col, formula].include?(nil)
1083
1268
 
1269
+ # Check for dynamic array functions.
1270
+ regex = /\bLET\(|\bSORT\(|\bLAMBDA\(|\bSINGLE\(|\bSORTBY\(|\bUNIQUE\(|\bXMATCH\(|\bFILTER\(|\bXLOOKUP\(|\bSEQUENCE\(|\bRANDARRAY\(|\bANCHORARRAY\(/
1271
+ if formula =~ regex
1272
+ return write_dynamic_array_formula(
1273
+ row, col, row, col, formula, format, value
1274
+ )
1275
+ end
1276
+
1277
+ # Hand off array formulas.
1084
1278
  if formula =~ /^\{=.*\}$/
1085
1279
  write_array_formula(row, col, row, col, formula, format, value)
1086
1280
  else
@@ -1088,7 +1282,7 @@ module Writexlsx
1088
1282
  store_row_col_max_min_values(row, col)
1089
1283
  formula = formula.sub(/^=/, '')
1090
1284
 
1091
- store_data_to_table(FormulaCellData.new(self, row, col, formula, format, value))
1285
+ store_data_to_table(FormulaCellData.new(formula, format, value), row, col)
1092
1286
  end
1093
1287
  end
1094
1288
 
@@ -1098,7 +1292,15 @@ module Writexlsx
1098
1292
  #
1099
1293
  def write_array_formula_base(type, *args)
1100
1294
  # Check for a cell reference in A1 notation and substitute row and column
1101
- row1, col1, row2, col2, formula, xf, value = row_col_notation(args)
1295
+ # Convert single cell to range
1296
+ if args.first.to_s =~ /^([A-Za-z]+[0-9]+)$/
1297
+ range = "#{::Regexp.last_match(1)}:#{::Regexp.last_match(1)}"
1298
+ params = [range] + args[1..]
1299
+ else
1300
+ params = args
1301
+ end
1302
+
1303
+ row1, col1, row2, col2, formula, xf, value = row_col_notation(params)
1102
1304
  raise WriteXLSXInsufficientArgumentError if [row1, col1, row2, col2, formula].include?(nil)
1103
1305
 
1104
1306
  # Swap last row/col with first row/col as necessary
@@ -1118,17 +1320,18 @@ module Writexlsx
1118
1320
  "#{xl_rowcol_to_cell(row1, col1)}:#{xl_rowcol_to_cell(row2, col2)}"
1119
1321
  end
1120
1322
 
1121
- # Remove array formula braces and the leading =.
1122
- formula = formula.sub(/^\{(.*)\}$/, '\1').sub(/^=/, '')
1323
+ # Modify the formula string, as needed.
1324
+ formula = prepare_formula(formula)
1123
1325
 
1124
1326
  store_data_to_table(
1125
1327
  if type == 'a'
1126
- FormulaArrayCellData.new(self, row1, col1, formula, xf, range, value)
1328
+ FormulaArrayCellData.new(formula, xf, range, value)
1127
1329
  elsif type == 'd'
1128
- DynamicFormulaArrayCellData.new(self, row1, col1, formula, xf, range, value)
1330
+ DynamicFormulaArrayCellData.new(formula, xf, range, value)
1129
1331
  else
1130
1332
  raise "invalid type in write_array_formula_base()."
1131
- end
1333
+ end,
1334
+ row1, col1
1132
1335
  )
1133
1336
 
1134
1337
  # Pad out the rest of the area with formatted zeroes.
@@ -1176,7 +1379,7 @@ module Writexlsx
1176
1379
  check_dimensions(row, col)
1177
1380
  store_row_col_max_min_values(row, col)
1178
1381
 
1179
- store_data_to_table(BooleanCellData.new(self, row, col, val, xf))
1382
+ store_data_to_table(BooleanCellData.new(val, xf), row, col)
1180
1383
  end
1181
1384
 
1182
1385
  #
@@ -1271,7 +1474,7 @@ module Writexlsx
1271
1474
 
1272
1475
  #
1273
1476
  # :call-seq:
1274
- # write_url(row, column, url [ , format, label, tip ] )
1477
+ # write_url(row, column, url [ , format, label, tip ])
1275
1478
  #
1276
1479
  # Write a hyperlink to a URL in the cell specified by +row+ and +column+.
1277
1480
  # The hyperlink is comprised of two elements: the visible label and
@@ -1304,7 +1507,7 @@ module Writexlsx
1304
1507
 
1305
1508
  #
1306
1509
  # :call-seq:
1307
- # write_date_time (row, col, date_string [ , format ] )
1510
+ # write_date_time (row, col, date_string [ , format ])
1308
1511
  #
1309
1512
  # Write a datetime string in ISO8601 "yyyy-mm-ddThh:mm:ss.ss" format as a
1310
1513
  # number representing an Excel date. format is optional.
@@ -1321,7 +1524,7 @@ module Writexlsx
1321
1524
  date_time = convert_date_time(str)
1322
1525
 
1323
1526
  if date_time
1324
- store_data_to_table(NumberCellData.new(self, row, col, date_time, xf))
1527
+ store_data_to_table(NumberCellData.new(date_time, xf), row, col)
1325
1528
  else
1326
1529
  # If the date isn't valid then write it as a string.
1327
1530
  write_string(*args)
@@ -1330,7 +1533,7 @@ module Writexlsx
1330
1533
 
1331
1534
  #
1332
1535
  # :call-seq:
1333
- # insert_chart(row, column, chart [ , x, y, x_scale, y_scale ] )
1536
+ # insert_chart(row, column, chart [ , x, y, x_scale, y_scale ])
1334
1537
  #
1335
1538
  # This method can be used to insert a Chart object into a worksheet.
1336
1539
  # The Chart must be created by the add_chart() Workbook method and
@@ -1343,12 +1546,13 @@ module Writexlsx
1343
1546
 
1344
1547
  if options.first.instance_of?(Hash)
1345
1548
  params = options.first
1346
- x_offset = params[:x_offset]
1347
- y_offset = params[:y_offset]
1348
- x_scale = params[:x_scale]
1349
- y_scale = params[:y_scale]
1350
- anchor = params[:object_position]
1351
-
1549
+ x_offset = params[:x_offset]
1550
+ y_offset = params[:y_offset]
1551
+ x_scale = params[:x_scale]
1552
+ y_scale = params[:y_scale]
1553
+ anchor = params[:object_position]
1554
+ description = params[:description]
1555
+ decorative = params[:decorative]
1352
1556
  else
1353
1557
  x_offset, y_offset, x_scale, y_scale, anchor = options
1354
1558
  end
@@ -1374,7 +1578,10 @@ module Writexlsx
1374
1578
  x_offset = chart.x_offset if ptrue?(chart.x_offset)
1375
1579
  y_offset = chart.y_offset if ptrue?(chart.y_offset)
1376
1580
 
1377
- @charts << [row, col, chart, x_offset, y_offset, x_scale, y_scale, anchor]
1581
+ @charts << [
1582
+ row, col, chart, x_offset, y_offset,
1583
+ x_scale, y_scale, anchor, description, decorative
1584
+ ]
1378
1585
  end
1379
1586
 
1380
1587
  #
@@ -1415,7 +1622,7 @@ module Writexlsx
1415
1622
 
1416
1623
  #
1417
1624
  # :call-seq:
1418
- # repeat_formula(row, column, formula [ , format ] )
1625
+ # repeat_formula(row, column, formula [ , format ])
1419
1626
  #
1420
1627
  # Deprecated. This is a writeexcel gem's method that is no longer
1421
1628
  # required by WriteXLSX.
@@ -1450,7 +1657,7 @@ module Writexlsx
1450
1657
 
1451
1658
  #
1452
1659
  # :call-seq:
1453
- # set_row(row [ , height, format, hidden, level, collapsed ] )
1660
+ # set_row(row [ , height, format, hidden, level, collapsed ])
1454
1661
  #
1455
1662
  # This method can be used to change the default properties of a row.
1456
1663
  # All parameters apart from +row+ are optional.
@@ -1866,7 +2073,9 @@ module Writexlsx
1866
2073
  def prepare_chart(index, chart_id, drawing_id) # :nodoc:
1867
2074
  drawing_type = 1
1868
2075
 
1869
- row, col, chart, x_offset, y_offset, x_scale, y_scale, anchor = @charts[index]
2076
+ row, col, chart, x_offset, y_offset,
2077
+ x_scale, y_scale, anchor, description, decorative = @charts[index]
2078
+
1870
2079
  chart.id = chart_id - 1
1871
2080
  x_scale ||= 0
1872
2081
  y_scale ||= 0
@@ -1884,7 +2093,7 @@ module Writexlsx
1884
2093
  name = chart.name
1885
2094
 
1886
2095
  # Create a Drawing object to use with worksheet unless one already exists.
1887
- drawing = Drawing.new(drawing_type, dimensions, 0, 0, name, nil, anchor, drawing_rel_index, 0, nil, 0)
2096
+ drawing = Drawing.new(drawing_type, dimensions, 0, 0, nil, anchor, drawing_rel_index, 0, nil, name, description, decorative)
1888
2097
  if drawings?
1889
2098
  @drawings.add_drawing_object(drawing)
1890
2099
  else
@@ -2603,7 +2812,7 @@ module Writexlsx
2603
2812
  height = (0.5 + (height * 9_525)).to_i
2604
2813
 
2605
2814
  # Create a Drawing object to use with worksheet unless one already exists.
2606
- drawing = Drawing.new(drawing_type, dimensions, width, height, name, nil, anchor, 0, 0, tip, decorative)
2815
+ drawing = Drawing.new(drawing_type, dimensions, width, height, nil, anchor, 0, 0, tip, name, description, decorative)
2607
2816
  if drawings?
2608
2817
  drawings = @drawings
2609
2818
  else
@@ -2616,7 +2825,7 @@ module Writexlsx
2616
2825
  end
2617
2826
  drawings.add_drawing_object(drawing)
2618
2827
 
2619
- drawing.description = description if description
2828
+ drawing.description = name unless description
2620
2829
 
2621
2830
  if url
2622
2831
  rel_type = '/hyperlink'
@@ -2689,7 +2898,7 @@ EOS
2689
2898
 
2690
2899
  #
2691
2900
  # :call-seq:
2692
- # insert_shape(row, col, shape [ , x, y, x_scale, y_scale ] )
2901
+ # insert_shape(row, col, shape [ , x, y, x_scale, y_scale ])
2693
2902
  #
2694
2903
  # Insert a shape into the worksheet.
2695
2904
  #
@@ -2760,7 +2969,7 @@ EOS
2760
2969
  drawing_type = 3
2761
2970
  drawing = Drawing.new(
2762
2971
  drawing_type, shape.dimensions, shape.width_emu, shape.height_emu,
2763
- shape.name, shape, shape.anchor, drawing_rel_index, 0, nil, 0
2972
+ shape, shape.anchor, drawing_rel_index, 0, shape.name, nil, 0
2764
2973
  )
2765
2974
  drawings.add_drawing_object(drawing)
2766
2975
  end
@@ -2787,6 +2996,9 @@ EOS
2787
2996
  "[0]!Button#{button_number}_Click"
2788
2997
  end
2789
2998
 
2999
+ # Set the alt text for the button.
3000
+ button.description = params[:description]
3001
+
2790
3002
  # Ensure that a width and height have been set.
2791
3003
  default_width = @default_col_pixels
2792
3004
  default_height = @default_row_pixels
@@ -2964,6 +3176,9 @@ EOS
2964
3176
  # TODO. Add pageBreakPreview mode when requested.
2965
3177
  attributes << %w[view pageLayout] if page_view?
2966
3178
 
3179
+ # Set the first visible cell.
3180
+ attributes << ['topLeftCell', @top_left_cell] if ptrue?(@top_left_cell)
3181
+
2967
3182
  # Set the zoom level.
2968
3183
  if @zoom != 100
2969
3184
  attributes << ['zoomScale', @zoom] unless page_view?
@@ -3119,7 +3334,7 @@ EOS
3119
3334
 
3120
3335
  def write_cell_column_dimension(row_num) # :nodoc:
3121
3336
  (@dim_colmin..@dim_colmax).each do |col_num|
3122
- @cell_data_table[row_num][col_num].write_cell if @cell_data_table[row_num][col_num]
3337
+ @cell_data_table[row_num][col_num].write_cell(self, row_num, col_num) if @cell_data_table[row_num][col_num]
3123
3338
  end
3124
3339
  end
3125
3340
 
@@ -3984,13 +4199,11 @@ EOS
3984
4199
  end
3985
4200
  end
3986
4201
 
3987
- def store_data_to_table(cell_data) # :nodoc:
3988
- row = cell_data.row
3989
- col = cell_data.col
4202
+ def store_data_to_table(cell_data, row, col) # :nodoc:
3990
4203
  if @cell_data_table[row]
3991
4204
  @cell_data_table[row][col] = cell_data
3992
4205
  else
3993
- @cell_data_table[row] = {}
4206
+ @cell_data_table[row] = []
3994
4207
  @cell_data_table[row][col] = cell_data
3995
4208
  end
3996
4209
  end
@@ -1,4 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
2
3
 
3
4
  #
4
5
  # from http://d.hatena.ne.jp/alunko/20071021
data/lib/write_xlsx.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'write_xlsx/workbook'
4
5
 
data/write_xlsx.gemspec CHANGED
@@ -11,6 +11,7 @@ Gem::Specification.new do |gem|
11
11
  gem.summary = 'write_xlsx is a gem to create a new file in the Excel 2007+ XLSX format.'
12
12
  gem.homepage = 'https://github.com/cxn03651/write_xlsx#readme'
13
13
  gem.license = 'MIT'
14
+ gem.required_ruby_version = '>= 2.5.0'
14
15
 
15
16
  gem.files = Dir.chdir(File.expand_path(__dir__)) do
16
17
  `git ls-files -z`.split("\x0").reject do |f|
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: write_xlsx
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.09.5
4
+ version: 1.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hideo NAKAMURA
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-18 00:00:00.000000000 Z
11
+ date: 2023-01-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubyzip
@@ -158,6 +158,7 @@ files:
158
158
  - examples/defined_name.rb
159
159
  - examples/demo.rb
160
160
  - examples/diag_border.rb
161
+ - examples/dynamic_arrays.rb
161
162
  - examples/formats.rb
162
163
  - examples/headers.rb
163
164
  - examples/hide_row_col.rb
@@ -166,6 +167,7 @@ files:
166
167
  - examples/ignore_errors.rb
167
168
  - examples/indent.rb
168
169
  - examples/keep_leading_zeros.rb
170
+ - examples/lambda.rb
169
171
  - examples/macros.rb
170
172
  - examples/merge1.rb
171
173
  - examples/merge2.rb
@@ -200,6 +202,8 @@ files:
200
202
  - examples/tables.rb
201
203
  - examples/update_range_format_with_params.rb
202
204
  - examples/vbaProject.bin
205
+ - examples/watermark.png
206
+ - examples/watermark.rb
203
207
  - lib/write_xlsx.rb
204
208
  - lib/write_xlsx/chart.rb
205
209
  - lib/write_xlsx/chart/area.rb
@@ -264,14 +268,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
264
268
  requirements:
265
269
  - - ">="
266
270
  - !ruby/object:Gem::Version
267
- version: '0'
271
+ version: 2.5.0
268
272
  required_rubygems_version: !ruby/object:Gem::Requirement
269
273
  requirements:
270
274
  - - ">="
271
275
  - !ruby/object:Gem::Version
272
276
  version: '0'
273
277
  requirements: []
274
- rubygems_version: 3.3.7
278
+ rubygems_version: 3.4.1
275
279
  signing_key:
276
280
  specification_version: 4
277
281
  summary: write_xlsx is a gem to create a new file in the Excel 2007+ XLSX format.