write_xlsx 0.97.0 → 1.04.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 (313) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Changes +78 -0
  4. data/LICENSE.txt +1 -1
  5. data/README.md +2 -2
  6. data/examples/a_simple.rb +1 -1
  7. data/examples/add_vba_project.rb +1 -1
  8. data/examples/array_formula.rb +1 -1
  9. data/examples/chart_area.rb +5 -2
  10. data/examples/chart_bar.rb +5 -2
  11. data/examples/chart_clustered.rb +1 -1
  12. data/examples/chart_column.rb +5 -2
  13. data/examples/chart_combined.rb +1 -1
  14. data/examples/chart_data_table.rb +9 -3
  15. data/examples/chart_data_tools.rb +25 -7
  16. data/examples/chart_doughnut.rb +17 -5
  17. data/examples/chart_gauge.rb +73 -0
  18. data/examples/chart_line.rb +90 -12
  19. data/examples/chart_pareto.rb +1 -1
  20. data/examples/chart_pie.rb +9 -3
  21. data/examples/chart_radar.rb +13 -4
  22. data/examples/chart_scatter.rb +5 -2
  23. data/examples/chart_secondary_axis.rb +5 -2
  24. data/examples/chart_stock.rb +1 -1
  25. data/examples/chart_styles.rb +1 -1
  26. data/examples/colors.rb +1 -1
  27. data/examples/data_validate.rb +1 -1
  28. data/examples/date_time.rb +1 -1
  29. data/examples/demo.rb +4 -1
  30. data/examples/formats.rb +1 -1
  31. data/examples/headers.rb +1 -1
  32. data/examples/hide_row_col.rb +1 -1
  33. data/examples/hide_sheet.rb +1 -1
  34. data/examples/hyperlink1.rb +1 -1
  35. data/examples/indent.rb +1 -1
  36. data/examples/macros.rb +1 -1
  37. data/examples/merge1.rb +1 -1
  38. data/examples/merge2.rb +1 -1
  39. data/examples/merge3.rb +1 -1
  40. data/examples/merge4.rb +1 -1
  41. data/examples/merge5.rb +1 -1
  42. data/examples/merge6.rb +1 -1
  43. data/examples/outline.rb +1 -1
  44. data/examples/outline_collapsed.rb +1 -1
  45. data/examples/panes.rb +1 -1
  46. data/examples/properties.rb +1 -1
  47. data/examples/regions.rb +1 -1
  48. data/examples/rich_strings.rb +1 -1
  49. data/examples/right_to_left.rb +1 -1
  50. data/examples/shape1.rb +1 -1
  51. data/examples/shape2.rb +1 -1
  52. data/examples/shape3.rb +1 -1
  53. data/examples/shape4.rb +1 -1
  54. data/examples/shape5.rb +1 -1
  55. data/examples/shape6.rb +1 -1
  56. data/examples/shape7.rb +1 -1
  57. data/examples/shape8.rb +1 -1
  58. data/examples/shape_all.rb +1 -1
  59. data/examples/sparklines1.rb +1 -1
  60. data/examples/sparklines2.rb +1 -1
  61. data/examples/stats.rb +1 -1
  62. data/examples/stats_ext.rb +1 -1
  63. data/examples/stocks.rb +1 -1
  64. data/examples/tab_colors.rb +1 -1
  65. data/examples/tables.rb +78 -43
  66. data/lib/write_xlsx/chart.rb +43 -35
  67. data/lib/write_xlsx/chart/area.rb +1 -1
  68. data/lib/write_xlsx/chart/axis.rb +2 -2
  69. data/lib/write_xlsx/chart/bar.rb +1 -1
  70. data/lib/write_xlsx/chart/column.rb +1 -1
  71. data/lib/write_xlsx/chart/doughnut.rb +1 -1
  72. data/lib/write_xlsx/chart/legend.rb +14 -0
  73. data/lib/write_xlsx/chart/line.rb +16 -2
  74. data/lib/write_xlsx/chart/pie.rb +30 -15
  75. data/lib/write_xlsx/chart/radar.rb +1 -1
  76. data/lib/write_xlsx/chart/scatter.rb +1 -1
  77. data/lib/write_xlsx/chart/stock.rb +1 -1
  78. data/lib/write_xlsx/chartsheet.rb +35 -7
  79. data/lib/write_xlsx/drawing.rb +86 -30
  80. data/lib/write_xlsx/format.rb +9 -9
  81. data/lib/write_xlsx/package/comments.rb +61 -58
  82. data/lib/write_xlsx/package/conditional_format.rb +9 -1
  83. data/lib/write_xlsx/package/relationships.rb +4 -4
  84. data/lib/write_xlsx/package/styles.rb +26 -8
  85. data/lib/write_xlsx/package/table.rb +13 -7
  86. data/lib/write_xlsx/package/vml.rb +20 -19
  87. data/lib/write_xlsx/shape.rb +4 -3
  88. data/lib/write_xlsx/sheets.rb +18 -16
  89. data/lib/write_xlsx/sparkline.rb +1 -1
  90. data/lib/write_xlsx/utility.rb +96 -7
  91. data/lib/write_xlsx/version.rb +1 -1
  92. data/lib/write_xlsx/workbook.rb +99 -49
  93. data/lib/write_xlsx/worksheet.rb +225 -145
  94. data/lib/write_xlsx/worksheet/data_validation.rb +10 -14
  95. data/lib/write_xlsx/worksheet/hyperlink.rb +16 -37
  96. data/test/chart/test_write_legend_pos.rb +9 -1
  97. data/test/chartsheet/test_write_sheet_protection.rb +91 -0
  98. data/test/drawing/test_drawing_chart_01.rb +6 -2
  99. data/test/drawing/test_drawing_image_01.rb +12 -3
  100. data/test/drawing/test_drawing_shape_01.rb +8 -5
  101. data/test/drawing/test_drawing_shape_02.rb +12 -5
  102. data/test/drawing/test_drawing_shape_03.rb +8 -5
  103. data/test/drawing/test_drawing_shape_04.rb +8 -24
  104. data/test/drawing/test_drawing_shape_05.rb +8 -5
  105. data/test/drawing/test_drawing_shape_06.rb +11 -6
  106. data/test/drawing/test_drawing_shape_07.rb +11 -6
  107. data/test/drawing/test_write_a_graphic_frame_locks.rb +1 -1
  108. data/test/drawing/test_write_c_chart.rb +1 -1
  109. data/test/drawing/test_write_c_nv_graphic_frame_pr.rb +1 -1
  110. data/test/drawing/test_write_c_nv_pr.rb +1 -1
  111. data/test/drawing/test_write_col.rb +1 -1
  112. data/test/drawing/test_write_col_off.rb +1 -1
  113. data/test/drawing/test_write_ext.rb +1 -1
  114. data/test/drawing/test_write_pos.rb +1 -1
  115. data/test/drawing/test_write_row.rb +1 -1
  116. data/test/drawing/test_write_row_off.rb +1 -1
  117. data/test/drawing/test_write_xfrm_extension.rb +1 -1
  118. data/test/drawing/test_write_xfrm_offset.rb +1 -1
  119. data/test/package/comments/test_comments_01.rb +54 -0
  120. data/test/package/comments/test_comments_02.rb +54 -0
  121. data/test/perl_output/chart_gauge.xlsx +0 -0
  122. data/test/perl_output/chart_line.xlsx +0 -0
  123. data/test/perl_output/comments2.xlsx +0 -0
  124. data/test/perl_output/formats.xlsx +0 -0
  125. data/test/perl_output/tables.xlsx +0 -0
  126. data/test/regression/images/happy.jpg +0 -0
  127. data/test/regression/images/red2.png +0 -0
  128. data/test/regression/test_array_formula03.rb +36 -0
  129. data/test/regression/test_autofilter08.rb +110 -0
  130. data/test/regression/test_autofilter09.rb +110 -0
  131. data/test/regression/test_autofilter10.rb +110 -0
  132. data/test/regression/test_chart_axis26.rb +10 -8
  133. data/test/regression/test_chart_axis27.rb +1 -1
  134. data/test/regression/test_chart_axis28.rb +1 -1
  135. data/test/regression/test_chart_axis29.rb +1 -1
  136. data/test/regression/test_chart_axis33.rb +1 -1
  137. data/test/regression/test_chart_axis42.rb +44 -0
  138. data/test/regression/test_chart_axis43.rb +44 -0
  139. data/test/regression/test_chart_axis44.rb +54 -0
  140. data/test/regression/test_chart_axis45.rb +54 -0
  141. data/test/regression/test_chart_axis46.rb +54 -0
  142. data/test/regression/test_chart_combined10.rb +43 -0
  143. data/test/regression/test_chart_combined11.rb +63 -0
  144. data/test/regression/test_chart_data_labels25.rb +1 -1
  145. data/test/regression/test_chart_doughnut07.rb +37 -0
  146. data/test/regression/test_chart_font09.rb +1 -1
  147. data/test/regression/test_chart_legend03.rb +41 -0
  148. data/test/regression/test_chart_legend04.rb +41 -0
  149. data/test/regression/test_chart_legend05.rb +41 -0
  150. data/test/regression/test_chart_legend06.rb +41 -0
  151. data/test/regression/test_chart_legend07.rb +38 -0
  152. data/test/regression/test_chart_line05.rb +43 -0
  153. data/test/regression/test_chart_line06.rb +43 -0
  154. data/test/regression/test_chart_size03.rb +4 -1
  155. data/test/regression/test_comment13.rb +36 -0
  156. data/test/regression/test_comment14.rb +29 -0
  157. data/test/regression/test_comment15.rb +28 -0
  158. data/test/regression/test_comment16.rb +34 -0
  159. data/test/regression/test_cond_format19.rb +64 -0
  160. data/test/regression/test_cond_format20.rb +43 -0
  161. data/test/regression/test_format15.rb +26 -0
  162. data/test/regression/test_header_image15.rb +36 -0
  163. data/test/regression/test_header_image16.rb +42 -0
  164. data/test/regression/test_header_image17.rb +46 -0
  165. data/test/regression/test_header_image18.rb +48 -0
  166. data/test/regression/test_header_image19.rb +36 -0
  167. data/test/regression/test_hyperlink32.rb +27 -0
  168. data/test/regression/test_hyperlink33.rb +28 -0
  169. data/test/regression/test_hyperlink34.rb +33 -0
  170. data/test/regression/test_hyperlink35.rb +39 -0
  171. data/test/regression/test_hyperlink36.rb +34 -0
  172. data/test/regression/test_hyperlink37.rb +33 -0
  173. data/test/regression/test_hyperlink38.rb +27 -0
  174. data/test/regression/test_hyperlink39.rb +27 -0
  175. data/test/regression/test_hyperlink40.rb +27 -0
  176. data/test/regression/test_hyperlink41.rb +27 -0
  177. data/test/regression/test_hyperlink42.rb +27 -0
  178. data/test/regression/test_hyperlink43.rb +27 -0
  179. data/test/regression/test_hyperlink44.rb +27 -0
  180. data/test/regression/test_hyperlink45.rb +27 -0
  181. data/test/regression/test_hyperlink47.rb +27 -0
  182. data/test/regression/test_hyperlink48.rb +31 -0
  183. data/test/regression/test_hyperlink49.rb +29 -0
  184. data/test/regression/test_image06.rb +5 -5
  185. data/test/regression/test_image08.rb +5 -4
  186. data/test/regression/test_image15.rb +4 -2
  187. data/test/regression/test_image28.rb +1 -1
  188. data/test/regression/test_image36.rb +26 -0
  189. data/test/regression/test_image44.rb +28 -0
  190. data/test/regression/test_image45.rb +29 -0
  191. data/test/regression/test_image46.rb +29 -0
  192. data/test/regression/test_image47.rb +28 -0
  193. data/test/regression/test_image48.rb +32 -0
  194. data/test/regression/test_image49.rb +38 -0
  195. data/test/regression/test_image50.rb +24 -0
  196. data/test/regression/test_image51.rb +30 -0
  197. data/test/regression/test_object_position01.rb +26 -0
  198. data/test/regression/test_object_position02.rb +26 -0
  199. data/test/regression/test_object_position03.rb +26 -0
  200. data/test/regression/test_object_position04.rb +44 -0
  201. data/test/regression/test_object_position06.rb +28 -0
  202. data/test/regression/test_object_position07.rb +28 -0
  203. data/test/regression/test_object_position08.rb +47 -0
  204. data/test/regression/test_object_position09.rb +50 -0
  205. data/test/regression/test_object_position10.rb +28 -0
  206. data/test/regression/test_object_position12.rb +25 -0
  207. data/test/regression/test_object_position13.rb +25 -0
  208. data/test/regression/test_object_position14.rb +25 -0
  209. data/test/regression/test_object_position15.rb +29 -0
  210. data/test/regression/test_object_position16.rb +29 -0
  211. data/test/regression/test_object_position17.rb +29 -0
  212. data/test/regression/test_object_position18.rb +29 -0
  213. data/test/regression/test_object_position19.rb +29 -0
  214. data/test/regression/test_object_position20.rb +29 -0
  215. data/test/regression/test_shape_connect01.rb +4 -2
  216. data/test/regression/test_table23.rb +56 -0
  217. data/test/regression/test_table24.rb +27 -0
  218. data/test/regression/test_table25.rb +27 -0
  219. data/test/regression/xlsx_files/array_formula03.xlsx +0 -0
  220. data/test/regression/xlsx_files/autofilter08.xlsx +0 -0
  221. data/test/regression/xlsx_files/autofilter09.xlsx +0 -0
  222. data/test/regression/xlsx_files/autofilter10.xlsx +0 -0
  223. data/test/regression/xlsx_files/chart_axis26.xlsx +0 -0
  224. data/test/regression/xlsx_files/chart_axis27.xlsx +0 -0
  225. data/test/regression/xlsx_files/chart_axis28.xlsx +0 -0
  226. data/test/regression/xlsx_files/chart_axis29.xlsx +0 -0
  227. data/test/regression/xlsx_files/chart_axis33.xlsx +0 -0
  228. data/test/regression/xlsx_files/chart_axis42.xlsx +0 -0
  229. data/test/regression/xlsx_files/chart_axis43.xlsx +0 -0
  230. data/test/regression/xlsx_files/chart_axis44.xlsx +0 -0
  231. data/test/regression/xlsx_files/chart_axis45.xlsx +0 -0
  232. data/test/regression/xlsx_files/chart_axis46.xlsx +0 -0
  233. data/test/regression/xlsx_files/chart_combined10.xlsx +0 -0
  234. data/test/regression/xlsx_files/chart_combined11.xlsx +0 -0
  235. data/test/regression/xlsx_files/chart_data_labels25.xlsx +0 -0
  236. data/test/regression/xlsx_files/chart_doughnut07.xlsx +0 -0
  237. data/test/regression/xlsx_files/chart_font09.xlsx +0 -0
  238. data/test/regression/xlsx_files/chart_legend03.xlsx +0 -0
  239. data/test/regression/xlsx_files/chart_legend04.xlsx +0 -0
  240. data/test/regression/xlsx_files/chart_legend05.xlsx +0 -0
  241. data/test/regression/xlsx_files/chart_legend06.xlsx +0 -0
  242. data/test/regression/xlsx_files/chart_legend07.xlsx +0 -0
  243. data/test/regression/xlsx_files/chart_line05.xlsx +0 -0
  244. data/test/regression/xlsx_files/chart_line06.xlsx +0 -0
  245. data/test/regression/xlsx_files/comment13.xlsx +0 -0
  246. data/test/regression/xlsx_files/comment14.xlsx +0 -0
  247. data/test/regression/xlsx_files/comment15.xlsx +0 -0
  248. data/test/regression/xlsx_files/comment16.xlsx +0 -0
  249. data/test/regression/xlsx_files/cond_format19.xlsx +0 -0
  250. data/test/regression/xlsx_files/cond_format20.xlsx +0 -0
  251. data/test/regression/xlsx_files/format15.xlsx +0 -0
  252. data/test/regression/xlsx_files/header_image15.xlsx +0 -0
  253. data/test/regression/xlsx_files/header_image16.xlsx +0 -0
  254. data/test/regression/xlsx_files/header_image17.xlsx +0 -0
  255. data/test/regression/xlsx_files/header_image18.xlsx +0 -0
  256. data/test/regression/xlsx_files/header_image19.xlsx +0 -0
  257. data/test/regression/xlsx_files/hyperlink32.xlsx +0 -0
  258. data/test/regression/xlsx_files/hyperlink33.xlsx +0 -0
  259. data/test/regression/xlsx_files/hyperlink34.xlsx +0 -0
  260. data/test/regression/xlsx_files/hyperlink35.xlsx +0 -0
  261. data/test/regression/xlsx_files/hyperlink36.xlsx +0 -0
  262. data/test/regression/xlsx_files/hyperlink37.xlsx +0 -0
  263. data/test/regression/xlsx_files/hyperlink38.xlsx +0 -0
  264. data/test/regression/xlsx_files/hyperlink39.xlsx +0 -0
  265. data/test/regression/xlsx_files/hyperlink40.xlsx +0 -0
  266. data/test/regression/xlsx_files/hyperlink41.xlsx +0 -0
  267. data/test/regression/xlsx_files/hyperlink42.xlsx +0 -0
  268. data/test/regression/xlsx_files/hyperlink43.xlsx +0 -0
  269. data/test/regression/xlsx_files/hyperlink44.xlsx +0 -0
  270. data/test/regression/xlsx_files/hyperlink45.xlsx +0 -0
  271. data/test/regression/xlsx_files/hyperlink46.xlsx +0 -0
  272. data/test/regression/xlsx_files/hyperlink47.xlsx +0 -0
  273. data/test/regression/xlsx_files/hyperlink48.xlsx +0 -0
  274. data/test/regression/xlsx_files/hyperlink49.xlsx +0 -0
  275. data/test/regression/xlsx_files/image06.xlsx +0 -0
  276. data/test/regression/xlsx_files/image36.xlsx +0 -0
  277. data/test/regression/xlsx_files/image44.xlsx +0 -0
  278. data/test/regression/xlsx_files/image45.xlsx +0 -0
  279. data/test/regression/xlsx_files/image46.xlsx +0 -0
  280. data/test/regression/xlsx_files/image47.xlsx +0 -0
  281. data/test/regression/xlsx_files/image48.xlsx +0 -0
  282. data/test/regression/xlsx_files/image49.xlsx +0 -0
  283. data/test/regression/xlsx_files/image50.xlsx +0 -0
  284. data/test/regression/xlsx_files/image51.xlsx +0 -0
  285. data/test/regression/xlsx_files/object_position01.xlsx +0 -0
  286. data/test/regression/xlsx_files/object_position02.xlsx +0 -0
  287. data/test/regression/xlsx_files/object_position03.xlsx +0 -0
  288. data/test/regression/xlsx_files/object_position04.xlsx +0 -0
  289. data/test/regression/xlsx_files/object_position06.xlsx +0 -0
  290. data/test/regression/xlsx_files/object_position07.xlsx +0 -0
  291. data/test/regression/xlsx_files/object_position08.xlsx +0 -0
  292. data/test/regression/xlsx_files/object_position09.xlsx +0 -0
  293. data/test/regression/xlsx_files/object_position10.xlsx +0 -0
  294. data/test/regression/xlsx_files/object_position12.xlsx +0 -0
  295. data/test/regression/xlsx_files/object_position13.xlsx +0 -0
  296. data/test/regression/xlsx_files/object_position14.xlsx +0 -0
  297. data/test/regression/xlsx_files/object_position15.xlsx +0 -0
  298. data/test/regression/xlsx_files/object_position16.xlsx +0 -0
  299. data/test/regression/xlsx_files/object_position17.xlsx +0 -0
  300. data/test/regression/xlsx_files/object_position18.xlsx +0 -0
  301. data/test/regression/xlsx_files/object_position19.xlsx +0 -0
  302. data/test/regression/xlsx_files/object_position20.xlsx +0 -0
  303. data/test/regression/xlsx_files/table23.xlsx +0 -0
  304. data/test/regression/xlsx_files/table24.xlsx +0 -0
  305. data/test/regression/xlsx_files/table25.xlsx +0 -0
  306. data/test/test_example_match.rb +955 -780
  307. data/test/workbook/test_check_sheetname.rb +51 -0
  308. data/test/workbook/test_write_workbook_view.rb +36 -0
  309. data/test/worksheet/test_write_data_validation_02.rb +17 -0
  310. data/test/worksheet/test_write_sheet_view.rb +19 -1
  311. data/write_xlsx.gemspec +1 -0
  312. metadata +349 -7
  313. data/test/package/comments/test_write_text_t.rb +0 -44
@@ -180,7 +180,7 @@ def initialize(formats, params = {}) # :nodoc:
180
180
  @xf_index = nil
181
181
  @dxf_index = nil
182
182
 
183
- @num_format = 0
183
+ @num_format = 'General'
184
184
  @num_format_index = 0
185
185
  @font_index = 0
186
186
  @font = 'Calibri'
@@ -248,11 +248,11 @@ def initialize(formats, params = {}) # :nodoc:
248
248
  #
249
249
  def copy(other)
250
250
  reserve = [
251
- :xf_index,
252
- :dxf_index,
253
- :xdf_format_indices,
254
- :palette
255
- ]
251
+ :xf_index,
252
+ :dxf_index,
253
+ :xdf_format_indices,
254
+ :palette
255
+ ]
256
256
  (instance_variables - reserve).each do |v|
257
257
  instance_variable_set(v, other.instance_variable_get(v))
258
258
  end
@@ -478,13 +478,13 @@ def self.color(color_code)
478
478
 
479
479
  colors = Colors::COLORS
480
480
 
481
+ # Return the default color if nil,
482
+ return 0x00 unless color_code
483
+
481
484
  if color_code.respond_to?(:to_str)
482
485
  # Return RGB style colors for processing later.
483
486
  return color_code if color_code =~ /^#[0-9A-F]{6}$/i
484
487
 
485
- # Return the default color if undef,
486
- return 0x00 unless color_code
487
-
488
488
  # or the color string converted to an integer,
489
489
  return colors[color_code.downcase.to_sym] if colors[color_code.downcase.to_sym]
490
490
 
@@ -14,28 +14,29 @@ class Comment
14
14
  DEFAULT_HEIGHT = 74
15
15
 
16
16
  attr_reader :row, :col, :string, :color, :vertices
17
+ attr_reader :font_size, :font_family
17
18
  attr_accessor :author, :visible
18
19
 
19
20
  def initialize(workbook, worksheet, row, col, string, options = {})
20
21
  options ||= {}
21
- @workbook = workbook
22
- @worksheet = worksheet
23
- @row, @col = row, col
22
+ @workbook = workbook
23
+ @worksheet = worksheet
24
+ @row, @col = row, col
24
25
  options_parse(row, col, options)
25
- @string = string[0, STR_MAX]
26
- @start_row ||= default_start_row(row)
27
- @start_col ||= default_start_col(col)
28
- @visible = options[:visible]
29
- @x_offset = options[:x_offset] || default_x_offset(col)
30
- @y_offset = options[:y_offset] || default_y_offset(row)
31
- @x_scale = options[:x_scale] || 1
32
- @y_scale = options[:y_scale] || 1
33
- @width = (0.5 + (options[:width] || DEFAULT_WIDTH) * @x_scale).to_i
34
- @height = (0.5 + (options[:height] || DEFAULT_HEIGHT) * @y_scale).to_i
35
- @vertices = @worksheet.position_object_pixels(
36
- @start_col, @start_row, @x_offset, @y_offset,
37
- @width, @height
38
- ) << [@width, @height]
26
+ @string = string[0, STR_MAX]
27
+ @start_row ||= default_start_row(row)
28
+ @start_col ||= default_start_col(col)
29
+ @visible = options[:visible]
30
+ @x_offset = options[:x_offset] || default_x_offset(col)
31
+ @y_offset = options[:y_offset] || default_y_offset(row)
32
+ @x_scale = options[:x_scale] || 1
33
+ @y_scale = options[:y_scale] || 1
34
+ @width = (0.5 + (options[:width] || DEFAULT_WIDTH) * @x_scale).to_i
35
+ @height = (0.5 + (options[:height] || DEFAULT_HEIGHT) * @y_scale).to_i
36
+ @vertices = @worksheet.position_object_pixels(
37
+ @start_col, @start_row, @x_offset, @y_offset,
38
+ @width, @height
39
+ ) << [@width, @height]
39
40
  end
40
41
 
41
42
  def backgrount_color(color)
@@ -154,7 +155,7 @@ def visibility
154
155
  #
155
156
  def fill_attributes
156
157
  [
157
- ['color2', '#ffffe1']
158
+ ['color2', '#ffffe1']
158
159
  ]
159
160
  end
160
161
 
@@ -163,9 +164,9 @@ def fill_attributes
163
164
  #
164
165
  def write_shadow
165
166
  attributes = [
166
- ['on', 't'],
167
- ['color', 'black'],
168
- ['obscured', 't']
167
+ ['on', 't'],
168
+ ['color', 'black'],
169
+ ['obscured', 't']
169
170
  ]
170
171
 
171
172
  @writer.empty_tag('v:shadow', attributes)
@@ -213,24 +214,31 @@ def writer=(w)
213
214
  @writer = w
214
215
  end
215
216
 
217
+ def font_name
218
+ @font
219
+ end
220
+
216
221
  private
217
222
 
218
223
  def options_parse(row, col, options)
219
- @color = backgrount_color(options[:color] || DEFAULT_COLOR)
220
- @author = options[:author]
221
- @start_cell = options[:start_cell]
224
+ @color = backgrount_color(options[:color] || DEFAULT_COLOR)
225
+ @author = options[:author]
226
+ @start_cell = options[:start_cell]
222
227
  @start_row, @start_col = if @start_cell
223
228
  substitute_cellref(@start_cell)
224
229
  else
225
230
  [ options[:start_row], options[:start_col] ]
226
231
  end
227
- @visible = options[:visible]
228
- @x_offset = options[:x_offset] || default_x_offset(col)
229
- @y_offset = options[:y_offset] || default_y_offset(row)
230
- @x_scale = options[:x_scale] || 1
231
- @y_scale = options[:y_scale] || 1
232
- @width = (0.5 + (options[:width] || DEFAULT_WIDTH) * @x_scale).to_i
233
- @height = (0.5 + (options[:height] || DEFAULT_HEIGHT) * @y_scale).to_i
232
+ @visible = options[:visible]
233
+ @x_offset = options[:x_offset] || default_x_offset(col)
234
+ @y_offset = options[:y_offset] || default_y_offset(row)
235
+ @x_scale = options[:x_scale] || 1
236
+ @y_scale = options[:y_scale] || 1
237
+ @font = options[:font] || 'Tahoma'
238
+ @font_size = options[:font_size] || 8
239
+ @font_family = options[:font_family] || 2
240
+ @width = (0.5 + (options[:width] || DEFAULT_WIDTH) * @x_scale).to_i
241
+ @height = (0.5 + (options[:height] || DEFAULT_HEIGHT) * @y_scale).to_i
234
242
  end
235
243
  end
236
244
 
@@ -249,13 +257,9 @@ def [](row)
249
257
  @comments[row]
250
258
  end
251
259
 
252
- def add(comment)
253
- if @comments[comment.row]
254
- @comments[comment.row][comment.col] = comment
255
- else
256
- @comments[comment.row] = {}
257
- @comments[comment.row][comment.col] = comment
258
- end
260
+ def add(workbook, worksheet, row, col, string, options)
261
+ @comments[row] ||= {}
262
+ @comments[row][col] = [workbook, worksheet, row, col, string, options]
259
263
  end
260
264
 
261
265
  def empty?
@@ -285,6 +289,10 @@ def sorted_comments
285
289
  # We sort the comments by row and column but that isn't strictly required.
286
290
  @comments.keys.sort.each do |row|
287
291
  @comments[row].keys.sort.each do |col|
292
+ user_options = @comments[row][col]
293
+ comment = Comment.new(*user_options)
294
+ @comments[row][col] = comment
295
+
288
296
  # Set comment visibility if required and not already user defined.
289
297
  @comments[row][col].visible ||= 1 if comments_visible?
290
298
 
@@ -366,36 +374,37 @@ def write_comment(comment)
366
374
  attributes << ['authorId', author_id]
367
375
 
368
376
  @writer.tag_elements('comment', attributes) do
369
- write_text(comment.string)
377
+ write_text(comment)
370
378
  end
371
379
  end
372
380
 
373
381
  #
374
382
  # Write the <text> element.
375
383
  #
376
- def write_text(text)
384
+ def write_text(comment)
377
385
  @writer.tag_elements('text') do
378
386
  # Write the text r element.
379
- write_text_r(text)
387
+ write_text_r(comment)
380
388
  end
381
389
  end
382
390
 
383
391
  #
384
392
  # Write the <r> element.
385
393
  #
386
- def write_text_r(text)
394
+ def write_text_r(comment)
387
395
  @writer.tag_elements('r') do
388
396
  # Write the rPr element.
389
- write_r_pr
397
+ write_r_pr(comment)
390
398
  # Write the text r element.
391
- write_text_t(text)
399
+ write_text_t(comment)
392
400
  end
393
401
  end
394
402
 
395
403
  #
396
404
  # Write the text <t> element.
397
405
  #
398
- def write_text_t(text)
406
+ def write_text_t(comment)
407
+ text = comment.string
399
408
  attributes = []
400
409
 
401
410
  attributes << ['xml:space', 'preserve'] if text =~ /^\s/ || text =~ /\s$/
@@ -406,25 +415,23 @@ def write_text_t(text)
406
415
  #
407
416
  # Write the <rPr> element.
408
417
  #
409
- def write_r_pr
418
+ def write_r_pr(comment)
410
419
  @writer.tag_elements('rPr') do
411
420
  # Write the sz element.
412
- write_sz
421
+ write_sz(comment.font_size)
413
422
  # Write the color element.
414
423
  write_color
415
424
  # Write the rFont element.
416
- write_r_font
425
+ write_r_font(comment.font_name)
417
426
  # Write the family element.
418
- write_family
427
+ write_family(comment.font_family)
419
428
  end
420
429
  end
421
430
 
422
431
  #
423
432
  # Write the <sz> element.
424
433
  #
425
- def write_sz
426
- val = 8
427
-
434
+ def write_sz(val)
428
435
  attributes = [ ['val', val] ]
429
436
 
430
437
  @writer.empty_tag('sz', attributes)
@@ -440,9 +447,7 @@ def write_color
440
447
  #
441
448
  # Write the <rFont> element.
442
449
  #
443
- def write_r_font
444
- val = 'Tahoma'
445
-
450
+ def write_r_font(val)
446
451
  attributes = [ ['val', val] ]
447
452
 
448
453
  @writer.empty_tag('rFont', attributes)
@@ -451,9 +456,7 @@ def write_r_font
451
456
  #
452
457
  # Write the <family> element.
453
458
  #
454
- def write_family
455
- val = 2
456
-
459
+ def write_family(val)
457
460
  attributes = [ ['val', val] ]
458
461
 
459
462
  @writer.empty_tag('family', attributes)
@@ -749,7 +749,15 @@ def write_cf_rule
749
749
  write_formula_tag(maximum)
750
750
  end
751
751
  else
752
- write_cf_rule_formula_tag(value)
752
+ quoted_value = value.to_s
753
+ numeric_regex = /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/
754
+ # String "Cell" values must be quoted, apart from ranges.
755
+ if !(quoted_value =~ /(\$?)([A-Z]{1,3})(\$?)(\d+)/) &&
756
+ !(quoted_value =~ numeric_regex) &&
757
+ !(quoted_value =~ /^".*"$/)
758
+ quoted_value = (%Q!"#{value}"!)
759
+ end
760
+ write_cf_rule_formula_tag(quoted_value)
753
761
  end
754
762
  end
755
763
  end
@@ -31,8 +31,8 @@ def assemble_xml_file
31
31
  #
32
32
  # Add container relationship to XLSX .rels xml files.
33
33
  #
34
- def add_document_relationship(type, target)
35
- @rels.push([Document_schema + type, target])
34
+ def add_document_relationship(type, target, target_mode = nil)
35
+ @rels.push([Document_schema + type, target, target_mode])
36
36
  end
37
37
 
38
38
  #
@@ -64,8 +64,8 @@ def add_worksheet_relationship(type, target, target_mode = nil)
64
64
  #
65
65
  def write_relationships
66
66
  attributes = [
67
- ['xmlns', Package_schema]
68
- ]
67
+ ['xmlns', Package_schema]
68
+ ]
69
69
 
70
70
  @writer.tag_elements('Relationships', attributes) do
71
71
  @rels.each { |rel| write_relationship(*rel) }
@@ -20,6 +20,7 @@ def initialize
20
20
  @dxf_formats = []
21
21
  @has_hyperlink = 0
22
22
  @hyperlink_font_id = 0
23
+ @has_comments = false
23
24
  end
24
25
 
25
26
  def set_xml_writer(filename)
@@ -37,7 +38,7 @@ def assemble_xml_file
37
38
  #
38
39
  def set_style_properties(
39
40
  xf_formats, palette, font_count, num_format_count, border_count,
40
- fill_count, custom_colors, dxf_formats
41
+ fill_count, custom_colors, dxf_formats, has_comments
41
42
  )
42
43
  @xf_formats = xf_formats
43
44
  @palette = palette
@@ -47,6 +48,7 @@ def set_style_properties(
47
48
  @fill_count = fill_count
48
49
  @custom_colors = custom_colors
49
50
  @dxf_formats = dxf_formats
51
+ @has_comments = has_comments
50
52
  end
51
53
 
52
54
  #
@@ -148,7 +150,14 @@ def write_num_fmt(num_fmt_id, format_code)
148
150
  # Write the <fonts> element.
149
151
  #
150
152
  def write_fonts
151
- write_format_elements('fonts', @font_count) do
153
+ count = @font_count
154
+
155
+ if @has_comments
156
+ # Add an extra font for comments.
157
+ count += 1
158
+ end
159
+
160
+ write_format_elements('fonts', count) do
152
161
  write_font_base
153
162
  end
154
163
  end
@@ -161,6 +170,21 @@ def write_font_base
161
170
  @hyperlink_font_id = format.font_index unless ptrue?(@hyperlink_font_id)
162
171
  end
163
172
  end
173
+ if @has_comments
174
+ write_comment_font
175
+ end
176
+ end
177
+
178
+ #
179
+ # Write the <font> element used for comments.
180
+ #
181
+ def write_comment_font
182
+ @writer.tag_elements('font') do
183
+ @writer.empty_tag('sz', [['val', 8]])
184
+ write_color('indexed', 81)
185
+ @writer.empty_tag( 'name', [['val', 'Tahoma']])
186
+ @writer.empty_tag( 'family', [['val', 2]])
187
+ end
164
188
  end
165
189
 
166
190
  #
@@ -394,12 +418,6 @@ def write_cell_style_xfs
394
418
  def write_cell_xfs
395
419
  formats = @xf_formats
396
420
 
397
- # Workaround for when the last format is used for the comment font
398
- # and shouldn't be used for cellXfs.
399
- last_format = formats[-1]
400
-
401
- formats.pop if last_format && last_format.font_only != 0
402
-
403
421
  attributes = [ ['count', formats.size] ]
404
422
 
405
423
  @writer.tag_elements('cellXfs', attributes) do
@@ -240,6 +240,11 @@ def handle_the_function_for_the_table_row(row2, col_data, col_num, user_data)
240
240
  # Convert a table total function to a worksheet formula.
241
241
  #
242
242
  def table_function_to_formula(function, col_name)
243
+ col_name = col_name.gsub(/'/, "''").
244
+ gsub(/#/, "'#").
245
+ gsub(/\[/, "'[").
246
+ gsub(/\]/, "']")
247
+
243
248
  subtotals = {
244
249
  :average => 101,
245
250
  :countNums => 102,
@@ -393,13 +398,14 @@ def write_table_column(col_data)
393
398
  # Write the <tableStyleInfo> element.
394
399
  #
395
400
  def write_table_style_info
396
- attributes = [
397
- ['name', @style],
398
- ['showFirstColumn', @show_first_col],
399
- ['showLastColumn', @show_last_col],
400
- ['showRowStripes', @show_row_stripes],
401
- ['showColumnStripes', @show_col_stripes]
402
- ]
401
+ attributes = []
402
+ if @style && @style != '' && @style != 'None'
403
+ attributes << ['name', @style]
404
+ end
405
+ attributes << ['showFirstColumn', @show_first_col]
406
+ attributes << ['showLastColumn', @show_last_col]
407
+ attributes << ['showRowStripes', @show_row_stripes]
408
+ attributes << ['showColumnStripes', @show_col_stripes]
403
409
 
404
410
  @writer.empty_tag('tableStyleInfo', attributes)
405
411
  end
@@ -17,9 +17,9 @@ def set_xml_writer(filename)
17
17
  end
18
18
 
19
19
  def assemble_xml_file(
20
- data_id, vml_shape_id, comments_data,
21
- buttons_data, header_images_data = []
22
- )
20
+ data_id, vml_shape_id, comments_data,
21
+ buttons_data, header_images_data = []
22
+ )
23
23
  return unless @writer
24
24
 
25
25
  write_xml_namespace do
@@ -29,9 +29,9 @@ def assemble_xml_file(
29
29
  z_index = 1
30
30
  unless buttons_data.empty?
31
31
  vml_shape_id, z_index =
32
- write_shape_type_and_shape(
33
- buttons_data,
34
- vml_shape_id, z_index) do
32
+ write_shape_type_and_shape(
33
+ buttons_data,
34
+ vml_shape_id, z_index) do
35
35
  write_button_shapetype
36
36
  end
37
37
  end
@@ -277,6 +277,7 @@ def write_image_shape(id, index, image_data)
277
277
  position = image_data[3]
278
278
  x_dpi = image_data[4]
279
279
  y_dpi = image_data[5]
280
+ ref_id = image_data[6]
280
281
 
281
282
  # Scale the height/width by the resolution, relative to 72dpi.
282
283
  width = width * 72.0 / x_dpi
@@ -294,20 +295,20 @@ def write_image_shape(id, index, image_data)
294
295
  end
295
296
 
296
297
  style = [
297
- "position:absolute", "margin-left:0", "margin-top:0",
298
- "width:#{width}pt", "height:#{height}pt",
299
- "z-index:#{index}"
300
- ].join(';')
298
+ "position:absolute", "margin-left:0", "margin-top:0",
299
+ "width:#{width}pt", "height:#{height}pt",
300
+ "z-index:#{index}"
301
+ ].join(';')
301
302
  attributes = [
302
- ['id', position],
303
- ['o:spid', "_x0000_s#{id}"],
304
- ['type', type],
305
- ['style', style]
306
- ]
303
+ ['id', position],
304
+ ['o:spid', "_x0000_s#{id}"],
305
+ ['type', type],
306
+ ['style', style]
307
+ ]
307
308
 
308
309
  @writer.tag_elements('v:shape', attributes) do
309
310
  # Write the v:imagedata element.
310
- write_imagedata(index, name)
311
+ write_imagedata(ref_id, name)
311
312
 
312
313
  # Write the o:lock element.
313
314
  write_rotation_lock
@@ -319,9 +320,9 @@ def write_image_shape(id, index, image_data)
319
320
  #
320
321
  def write_imagedata(index, o_title)
321
322
  attributes = [
322
- ['o:relid', "rId#{index}"],
323
- ['o:title', o_title]
324
- ]
323
+ ['o:relid', "rId#{index}"],
324
+ ['o:title', o_title]
325
+ ]
325
326
 
326
327
  @writer.empty_tag('v:imagedata', attributes)
327
328
  end