write_xlsx 0.0.4 → 0.51.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 (688) hide show
  1. data/Gemfile +4 -2
  2. data/README.rdoc +14 -12
  3. data/Rakefile +8 -8
  4. data/VERSION +1 -1
  5. data/examples/chart_secondary_axis.rb +55 -0
  6. data/examples/date_time.rb +84 -0
  7. data/examples/panes.rb +108 -0
  8. data/examples/regions.rb +49 -0
  9. data/examples/shape1.rb +36 -0
  10. data/examples/shape2.rb +53 -0
  11. data/examples/shape3.rb +32 -0
  12. data/examples/shape4.rb +55 -0
  13. data/examples/shape5.rb +48 -0
  14. data/examples/shape6.rb +48 -0
  15. data/examples/shape7.rb +74 -0
  16. data/examples/shape8.rb +73 -0
  17. data/examples/shape_all.rb +241 -0
  18. data/examples/stats.rb +69 -0
  19. data/examples/stats_ext.rb +77 -0
  20. data/examples/stocks.rb +73 -0
  21. data/examples/tables.rb +360 -0
  22. data/lib/write_xlsx.rb +25 -1
  23. data/lib/write_xlsx/chart.rb +656 -260
  24. data/lib/write_xlsx/chart/area.rb +41 -7
  25. data/lib/write_xlsx/chart/bar.rb +16 -17
  26. data/lib/write_xlsx/chart/column.rb +5 -15
  27. data/lib/write_xlsx/chart/line.rb +15 -6
  28. data/lib/write_xlsx/chart/pie.rb +7 -21
  29. data/lib/write_xlsx/chart/scatter.rb +90 -20
  30. data/lib/write_xlsx/chart/stock.rb +24 -43
  31. data/lib/write_xlsx/chartsheet.rb +29 -11
  32. data/lib/write_xlsx/drawing.rb +354 -35
  33. data/lib/write_xlsx/format.rb +72 -21
  34. data/lib/write_xlsx/package/app.rb +2 -5
  35. data/lib/write_xlsx/package/comments.rb +5 -1
  36. data/lib/write_xlsx/package/content_types.rb +10 -0
  37. data/lib/write_xlsx/package/packager.rb +41 -7
  38. data/lib/write_xlsx/package/relationships.rb +1 -1
  39. data/lib/write_xlsx/package/shared_strings.rb +36 -8
  40. data/lib/write_xlsx/package/styles.rb +12 -9
  41. data/lib/write_xlsx/package/table.rb +194 -0
  42. data/lib/write_xlsx/package/vml.rb +26 -27
  43. data/lib/write_xlsx/package/xml_writer_simple.rb +25 -4
  44. data/lib/write_xlsx/shape.rb +172 -0
  45. data/lib/write_xlsx/utility.rb +20 -0
  46. data/lib/write_xlsx/workbook.rb +499 -141
  47. data/lib/write_xlsx/worksheet.rb +1162 -153
  48. data/test/chart/test_add_series.rb +43 -4
  49. data/test/chart/test_write_d_lbls.rb +274 -0
  50. data/test/chart/test_write_major_gridlines.rb +1 -1
  51. data/test/chartsheet/test_chartsheet01.rb +31 -0
  52. data/test/drawing/test_drawing_shape_01.rb +68 -0
  53. data/test/drawing/test_drawing_shape_02.rb +73 -0
  54. data/test/drawing/test_drawing_shape_03.rb +38 -0
  55. data/test/drawing/test_drawing_shape_04.rb +121 -0
  56. data/test/drawing/test_drawing_shape_05.rb +45 -0
  57. data/test/drawing/test_drawing_shape_06.rb +42 -0
  58. data/test/drawing/test_drawing_shape_07.rb +47 -0
  59. data/test/drawing/test_write_a_graphic_frame_locks.rb +18 -0
  60. data/test/drawing/test_write_c_chart.rb +18 -0
  61. data/test/drawing/test_write_c_nv_graphic_frame_pr.rb +28 -0
  62. data/test/drawing/test_write_c_nv_pr.rb +18 -0
  63. data/test/drawing/test_write_col.rb +18 -0
  64. data/test/drawing/test_write_col_off.rb +18 -0
  65. data/test/drawing/test_write_ext.rb +18 -0
  66. data/test/drawing/test_write_pos.rb +18 -0
  67. data/test/drawing/test_write_row.rb +18 -0
  68. data/test/drawing/test_write_row_off.rb +18 -0
  69. data/test/drawing/test_write_xfrm_extension.rb +18 -0
  70. data/test/drawing/test_write_xfrm_offset.rb +18 -0
  71. data/test/helper.rb +93 -50
  72. data/test/package/shared_strings/test_write_si.rb +10 -1
  73. data/test/package/table/test_table01.rb +42 -0
  74. data/test/package/table/test_table02.rb +44 -0
  75. data/test/package/table/test_table03.rb +48 -0
  76. data/test/package/table/test_table04.rb +46 -0
  77. data/test/package/table/test_table05.rb +46 -0
  78. data/test/package/table/test_table06.rb +52 -0
  79. data/test/package/table/test_table07.rb +47 -0
  80. data/test/package/table/test_table08.rb +53 -0
  81. data/test/package/table/test_table09.rb +65 -0
  82. data/test/package/table/test_table10.rb +45 -0
  83. data/test/package/table/test_table11.rb +60 -0
  84. data/test/package/table/test_table12.rb +60 -0
  85. data/test/package/table/test_write_auto_filter.rb +16 -0
  86. data/test/package/table/test_write_table_column.rb +15 -0
  87. data/test/package/table/test_write_table_style_info.rb +25 -0
  88. data/test/package/table/test_write_xml_declaration.rb +15 -0
  89. data/test/perl_output/a_simple.xlsx +0 -0
  90. data/test/perl_output/array_formula.xlsx +0 -0
  91. data/test/perl_output/chart_secondary_axis.xlsx +0 -0
  92. data/test/perl_output/data_validate.xlsx +0 -0
  93. data/test/perl_output/date_time.xlsx +0 -0
  94. data/test/perl_output/demo.xlsx +0 -0
  95. data/test/perl_output/formats.xlsx +0 -0
  96. data/test/perl_output/headers.xlsx +0 -0
  97. data/test/perl_output/outline_collapsed.xlsx +0 -0
  98. data/test/perl_output/panes.xlsx +0 -0
  99. data/test/perl_output/regions.xlsx +0 -0
  100. data/test/perl_output/shape1.xlsx +0 -0
  101. data/test/perl_output/shape2.xlsx +0 -0
  102. data/test/perl_output/shape3.xlsx +0 -0
  103. data/test/perl_output/shape4.xlsx +0 -0
  104. data/test/perl_output/shape5.xlsx +0 -0
  105. data/test/perl_output/shape6.xlsx +0 -0
  106. data/test/perl_output/shape7.xlsx +0 -0
  107. data/test/perl_output/shape8.xlsx +0 -0
  108. data/test/perl_output/shape_all.xlsx +0 -0
  109. data/test/perl_output/stats.xlsx +0 -0
  110. data/test/perl_output/stats_ext.xlsx +0 -0
  111. data/test/perl_output/stocks.xlsx +0 -0
  112. data/test/perl_output/tables.xlsx +0 -0
  113. data/test/regression/images/blue.jpg +0 -0
  114. data/test/regression/images/blue.png +0 -0
  115. data/test/regression/images/grey.jpg +0 -0
  116. data/test/regression/images/grey.png +0 -0
  117. data/test/regression/images/red.bmp +0 -0
  118. data/test/regression/images/red.jpg +0 -0
  119. data/test/regression/images/red.png +0 -0
  120. data/test/regression/images/yellow.jpg +0 -0
  121. data/test/regression/images/yellow.png +0 -0
  122. data/test/regression/test_array_formula01.rb +31 -0
  123. data/test/regression/test_array_formula02.rb +32 -0
  124. data/test/regression/test_autofilter00.rb +84 -0
  125. data/test/regression/test_autofilter01.rb +86 -0
  126. data/test/regression/test_autofilter02.rb +104 -0
  127. data/test/regression/test_autofilter03.rb +104 -0
  128. data/test/regression/test_autofilter04.rb +107 -0
  129. data/test/regression/test_autofilter05.rb +108 -0
  130. data/test/regression/test_autofilter06.rb +108 -0
  131. data/test/regression/test_autofilter07.rb +107 -0
  132. data/test/regression/test_chart_area01.rb +45 -0
  133. data/test/regression/test_chart_area02.rb +45 -0
  134. data/test/regression/test_chart_area03.rb +45 -0
  135. data/test/regression/test_chart_axis01.rb +46 -0
  136. data/test/regression/test_chart_axis02.rb +46 -0
  137. data/test/regression/test_chart_axis03.rb +68 -0
  138. data/test/regression/test_chart_axis04.rb +53 -0
  139. data/test/regression/test_chart_axis05.rb +48 -0
  140. data/test/regression/test_chart_axis06.rb +50 -0
  141. data/test/regression/test_chart_axis07.rb +54 -0
  142. data/test/regression/test_chart_axis08.rb +53 -0
  143. data/test/regression/test_chart_axis09.rb +47 -0
  144. data/test/regression/test_chart_axis10.rb +53 -0
  145. data/test/regression/test_chart_axis11.rb +47 -0
  146. data/test/regression/test_chart_axis12.rb +47 -0
  147. data/test/regression/test_chart_axis13.rb +53 -0
  148. data/test/regression/test_chart_axis14.rb +67 -0
  149. data/test/regression/test_chart_axis15.rb +48 -0
  150. data/test/regression/test_chart_axis16.rb +70 -0
  151. data/test/regression/test_chart_axis17.rb +46 -0
  152. data/test/regression/test_chart_axis18.rb +44 -0
  153. data/test/regression/test_chart_axis19.rb +46 -0
  154. data/test/regression/test_chart_axis20.rb +46 -0
  155. data/test/regression/test_chart_axis21.rb +50 -0
  156. data/test/regression/test_chart_bar01.rb +44 -0
  157. data/test/regression/test_chart_bar02.rb +55 -0
  158. data/test/regression/test_chart_bar03.rb +67 -0
  159. data/test/regression/test_chart_bar04.rb +70 -0
  160. data/test/regression/test_chart_bar05.rb +43 -0
  161. data/test/regression/test_chart_bar06.rb +50 -0
  162. data/test/regression/test_chart_bar07.rb +54 -0
  163. data/test/regression/test_chart_bar08.rb +44 -0
  164. data/test/regression/test_chart_bar09.rb +43 -0
  165. data/test/regression/test_chart_bar10.rb +47 -0
  166. data/test/regression/test_chart_bar11.rb +71 -0
  167. data/test/regression/test_chart_bar12.rb +43 -0
  168. data/test/regression/test_chart_bar13.rb +53 -0
  169. data/test/regression/test_chart_bar14.rb +63 -0
  170. data/test/regression/test_chart_bar15.rb +53 -0
  171. data/test/regression/test_chart_bar16.rb +51 -0
  172. data/test/regression/test_chart_bar17.rb +47 -0
  173. data/test/regression/test_chart_bar18.rb +58 -0
  174. data/test/regression/test_chart_bar19.rb +50 -0
  175. data/test/regression/test_chart_bar20.rb +47 -0
  176. data/test/regression/test_chart_bar21.rb +53 -0
  177. data/test/regression/test_chart_bar22.rb +68 -0
  178. data/test/regression/test_chart_bar23.rb +62 -0
  179. data/test/regression/test_chart_bar24.rb +46 -0
  180. data/test/regression/test_chart_blank01.rb +41 -0
  181. data/test/regression/test_chart_blank02.rb +41 -0
  182. data/test/regression/test_chart_blank03.rb +41 -0
  183. data/test/regression/test_chart_blank04.rb +41 -0
  184. data/test/regression/test_chart_blank05.rb +46 -0
  185. data/test/regression/test_chart_blank06.rb +41 -0
  186. data/test/regression/test_chart_column01.rb +43 -0
  187. data/test/regression/test_chart_column02.rb +45 -0
  188. data/test/regression/test_chart_column03.rb +45 -0
  189. data/test/regression/test_chart_column04.rb +45 -0
  190. data/test/regression/test_chart_column05.rb +39 -0
  191. data/test/regression/test_chart_column06.rb +46 -0
  192. data/test/regression/test_chart_crossing01.rb +50 -0
  193. data/test/regression/test_chart_crossing02.rb +48 -0
  194. data/test/regression/test_chart_crossing03.rb +53 -0
  195. data/test/regression/test_chart_crossing04.rb +53 -0
  196. data/test/regression/test_chart_format01.rb +44 -0
  197. data/test/regression/test_chart_format02.rb +45 -0
  198. data/test/regression/test_chart_format03.rb +46 -0
  199. data/test/regression/test_chart_format04.rb +45 -0
  200. data/test/regression/test_chart_format05.rb +45 -0
  201. data/test/regression/test_chart_format06.rb +52 -0
  202. data/test/regression/test_chart_format07.rb +57 -0
  203. data/test/regression/test_chart_format08.rb +52 -0
  204. data/test/regression/test_chart_format09.rb +56 -0
  205. data/test/regression/test_chart_format10.rb +59 -0
  206. data/test/regression/test_chart_format11.rb +63 -0
  207. data/test/regression/test_chart_format12.rb +60 -0
  208. data/test/regression/test_chart_format13.rb +52 -0
  209. data/test/regression/test_chart_format14.rb +56 -0
  210. data/test/regression/test_chart_format15.rb +54 -0
  211. data/test/regression/test_chart_format16.rb +57 -0
  212. data/test/regression/test_chart_format17.rb +40 -0
  213. data/test/regression/test_chart_format18.rb +44 -0
  214. data/test/regression/test_chart_line01.rb +39 -0
  215. data/test/regression/test_chart_line02.rb +45 -0
  216. data/test/regression/test_chart_name01.rb +46 -0
  217. data/test/regression/test_chart_name02.rb +58 -0
  218. data/test/regression/test_chart_name03.rb +58 -0
  219. data/test/regression/test_chart_pie01.rb +36 -0
  220. data/test/regression/test_chart_scatter01.rb +45 -0
  221. data/test/regression/test_chart_scatter02.rb +49 -0
  222. data/test/regression/test_chart_scatter03.rb +49 -0
  223. data/test/regression/test_chart_scatter04.rb +49 -0
  224. data/test/regression/test_chart_scatter05.rb +49 -0
  225. data/test/regression/test_chart_scatter06.rb +51 -0
  226. data/test/regression/test_chart_scatter07.rb +60 -0
  227. data/test/regression/test_chart_sparse01.rb +54 -0
  228. data/test/regression/test_chart_stock01.rb +72 -0
  229. data/test/regression/test_chart_stock02.rb +73 -0
  230. data/test/regression/test_chart_str01.rb +48 -0
  231. data/test/regression/test_chart_str02.rb +52 -0
  232. data/test/regression/test_chartsheet01.rb +46 -0
  233. data/test/regression/test_chartsheet02.rb +50 -0
  234. data/test/regression/test_chartsheet03.rb +48 -0
  235. data/test/regression/test_chartsheet04.rb +48 -0
  236. data/test/regression/test_chartsheet05.rb +48 -0
  237. data/test/regression/test_chartsheet06.rb +48 -0
  238. data/test/regression/test_chartsheet07.rb +57 -0
  239. data/test/regression/test_chartsheet08.rb +61 -0
  240. data/test/regression/test_chartsheet09.rb +52 -0
  241. data/test/regression/test_comment01.rb +27 -0
  242. data/test/regression/test_comment02.rb +28 -0
  243. data/test/regression/test_comment03.rb +32 -0
  244. data/test/regression/test_comment04.rb +37 -0
  245. data/test/regression/test_comment06.rb +34 -0
  246. data/test/regression/test_comment07.rb +36 -0
  247. data/test/regression/test_comment08.rb +36 -0
  248. data/test/regression/test_comment09.rb +32 -0
  249. data/test/regression/test_comment10.rb +31 -0
  250. data/test/regression/test_cond_format01.rb +46 -0
  251. data/test/regression/test_cond_format02.rb +41 -0
  252. data/test/regression/test_cond_format03.rb +52 -0
  253. data/test/regression/test_cond_format04.rb +51 -0
  254. data/test/regression/test_cond_format05.rb +41 -0
  255. data/test/regression/test_cond_format06.rb +45 -0
  256. data/test/regression/test_cond_format07.rb +62 -0
  257. data/test/regression/test_cond_format08.rb +46 -0
  258. data/test/regression/test_cond_format10.rb +43 -0
  259. data/test/regression/test_cond_format11.rb +47 -0
  260. data/test/regression/test_cond_format12.rb +47 -0
  261. data/test/regression/test_custom_colors01.rb +33 -0
  262. data/test/regression/test_date_1904_01.rb +36 -0
  263. data/test/regression/test_date_1904_02.rb +39 -0
  264. data/test/regression/test_defined_name01.rb +47 -0
  265. data/test/regression/test_escapes01.rb +37 -0
  266. data/test/regression/test_escapes02.rb +33 -0
  267. data/test/regression/test_escapes03.rb +34 -0
  268. data/test/regression/test_fit_to_pages01.rb +37 -0
  269. data/test/regression/test_fit_to_pages02.rb +37 -0
  270. data/test/regression/test_fit_to_pages03.rb +37 -0
  271. data/test/regression/test_fit_to_pages04.rb +37 -0
  272. data/test/regression/test_fit_to_pages05.rb +37 -0
  273. data/test/regression/test_format01.rb +35 -0
  274. data/test/regression/test_format02.rb +47 -0
  275. data/test/regression/test_format03.rb +31 -0
  276. data/test/regression/test_format04.rb +41 -0
  277. data/test/regression/test_gridlines01.rb +36 -0
  278. data/test/regression/test_hyperlink01.rb +23 -0
  279. data/test/regression/test_hyperlink02.rb +27 -0
  280. data/test/regression/test_hyperlink03.rb +32 -0
  281. data/test/regression/test_hyperlink04.rb +31 -0
  282. data/test/regression/test_hyperlink05.rb +26 -0
  283. data/test/regression/test_hyperlink06.rb +25 -0
  284. data/test/regression/test_hyperlink07.rb +24 -0
  285. data/test/regression/test_hyperlink08.rb +24 -0
  286. data/test/regression/test_hyperlink09.rb +25 -0
  287. data/test/regression/test_hyperlink10.rb +24 -0
  288. data/test/regression/test_hyperlink11.rb +24 -0
  289. data/test/regression/test_hyperlink12.rb +25 -0
  290. data/test/regression/test_hyperlink13.rb +24 -0
  291. data/test/regression/test_hyperlink14.rb +24 -0
  292. data/test/regression/test_hyperlink15.rb +26 -0
  293. data/test/regression/test_hyperlink16.rb +26 -0
  294. data/test/regression/test_hyperlink17.rb +27 -0
  295. data/test/regression/test_hyperlink18.rb +27 -0
  296. data/test/regression/test_image01.rb +23 -0
  297. data/test/regression/test_image02.rb +23 -0
  298. data/test/regression/test_image03.rb +23 -0
  299. data/test/regression/test_image04.rb +23 -0
  300. data/test/regression/test_image05.rb +26 -0
  301. data/test/regression/test_image06.rb +36 -0
  302. data/test/regression/test_image07.rb +25 -0
  303. data/test/regression/test_outline01.rb +86 -0
  304. data/test/regression/test_outline02.rb +89 -0
  305. data/test/regression/test_outline03.rb +59 -0
  306. data/test/regression/test_outline04.rb +55 -0
  307. data/test/regression/test_outline05.rb +90 -0
  308. data/test/regression/test_outline06.rb +89 -0
  309. data/test/regression/test_page_breaks01.rb +36 -0
  310. data/test/regression/test_page_breaks02.rb +36 -0
  311. data/test/regression/test_page_breaks03.rb +36 -0
  312. data/test/regression/test_page_breaks04.rb +36 -0
  313. data/test/regression/test_page_breaks05.rb +36 -0
  314. data/test/regression/test_page_breaks06.rb +37 -0
  315. data/test/regression/test_page_view01.rb +36 -0
  316. data/test/regression/test_panes01.rb +66 -0
  317. data/test/regression/test_print_across01.rb +37 -0
  318. data/test/regression/test_print_area01.rb +36 -0
  319. data/test/regression/test_print_area02.rb +36 -0
  320. data/test/regression/test_print_area03.rb +36 -0
  321. data/test/regression/test_print_area04.rb +36 -0
  322. data/test/regression/test_print_area05.rb +36 -0
  323. data/test/regression/test_print_area06.rb +36 -0
  324. data/test/regression/test_print_area07.rb +37 -0
  325. data/test/regression/test_print_options01.rb +36 -0
  326. data/test/regression/test_print_options02.rb +36 -0
  327. data/test/regression/test_print_options03.rb +36 -0
  328. data/test/regression/test_print_options04.rb +36 -0
  329. data/test/regression/test_print_options05.rb +39 -0
  330. data/test/regression/test_print_options06.rb +37 -0
  331. data/test/regression/test_print_scale01.rb +37 -0
  332. data/test/regression/test_print_scale02.rb +37 -0
  333. data/test/regression/test_properties01.rb +40 -0
  334. data/test/regression/test_repeat01.rb +36 -0
  335. data/test/regression/test_repeat02.rb +36 -0
  336. data/test/regression/test_repeat03.rb +37 -0
  337. data/test/regression/test_repeat04.rb +36 -0
  338. data/test/regression/test_repeat05.rb +43 -0
  339. data/test/regression/test_rich_string01.rb +28 -0
  340. data/test/regression/test_rich_string02.rb +28 -0
  341. data/test/regression/test_rich_string03.rb +28 -0
  342. data/test/regression/test_rich_string04.rb +28 -0
  343. data/test/regression/test_rich_string05.rb +30 -0
  344. data/test/regression/test_rich_string06.rb +27 -0
  345. data/test/regression/test_rich_string07.rb +33 -0
  346. data/test/regression/test_rich_string08.rb +29 -0
  347. data/test/regression/test_rich_string09.rb +31 -0
  348. data/test/regression/test_rich_string10.rb +30 -0
  349. data/test/regression/test_rich_string11.rb +29 -0
  350. data/test/regression/test_row_col_format01.rb +24 -0
  351. data/test/regression/test_row_col_format02.rb +25 -0
  352. data/test/regression/test_row_col_format03.rb +24 -0
  353. data/test/regression/test_row_col_format04.rb +25 -0
  354. data/test/regression/test_row_col_format05.rb +26 -0
  355. data/test/regression/test_row_col_format06.rb +29 -0
  356. data/test/regression/test_row_col_format07.rb +24 -0
  357. data/test/regression/test_row_col_format08.rb +34 -0
  358. data/test/regression/test_row_col_format09.rb +33 -0
  359. data/test/regression/test_row_col_format10.rb +24 -0
  360. data/test/regression/test_row_col_format11.rb +23 -0
  361. data/test/regression/test_row_col_format12.rb +23 -0
  362. data/test/regression/test_row_col_format13.rb +28 -0
  363. data/test/regression/test_row_col_format14.rb +28 -0
  364. data/test/regression/test_shape_connect01.rb +46 -0
  365. data/test/regression/test_shape_connect02.rb +42 -0
  366. data/test/regression/test_shape_connect03.rb +78 -0
  367. data/test/regression/test_shape_connect04.rb +75 -0
  368. data/test/regression/test_shape_scale01.rb +47 -0
  369. data/test/regression/test_shape_stencil01.rb +44 -0
  370. data/test/regression/test_shared_strings01.rb +34 -0
  371. data/test/regression/test_shared_strings02.rb +47 -0
  372. data/test/regression/test_simple01.rb +24 -0
  373. data/test/regression/test_simple02.rb +32 -0
  374. data/test/regression/test_tab_color01.rb +29 -0
  375. data/test/regression/test_table01.rb +27 -0
  376. data/test/regression/test_table02.rb +37 -0
  377. data/test/regression/test_table03.rb +30 -0
  378. data/test/regression/test_table04.rb +34 -0
  379. data/test/regression/test_table05.rb +38 -0
  380. data/test/regression/test_table06.rb +41 -0
  381. data/test/regression/test_table07.rb +29 -0
  382. data/test/regression/test_table08.rb +48 -0
  383. data/test/regression/test_table09.rb +65 -0
  384. data/test/regression/test_table10.rb +68 -0
  385. data/test/regression/test_table11.rb +37 -0
  386. data/test/regression/test_table12.rb +36 -0
  387. data/test/regression/test_table13.rb +51 -0
  388. data/test/regression/test_table14.rb +51 -0
  389. data/test/regression/xlsx_files/array_formula01.xlsx +0 -0
  390. data/test/regression/xlsx_files/array_formula02.xlsx +0 -0
  391. data/test/regression/xlsx_files/autofilter00.xlsx +0 -0
  392. data/test/regression/xlsx_files/autofilter01.xlsx +0 -0
  393. data/test/regression/xlsx_files/autofilter02.xlsx +0 -0
  394. data/test/regression/xlsx_files/autofilter03.xlsx +0 -0
  395. data/test/regression/xlsx_files/autofilter04.xlsx +0 -0
  396. data/test/regression/xlsx_files/autofilter05.xlsx +0 -0
  397. data/test/regression/xlsx_files/autofilter06.xlsx +0 -0
  398. data/test/regression/xlsx_files/autofilter07.xlsx +0 -0
  399. data/test/regression/xlsx_files/chart_area01.xlsx +0 -0
  400. data/test/regression/xlsx_files/chart_area02.xlsx +0 -0
  401. data/test/regression/xlsx_files/chart_area03.xlsx +0 -0
  402. data/test/regression/xlsx_files/chart_area04.xlsx +0 -0
  403. data/test/regression/xlsx_files/chart_axis01.xlsx +0 -0
  404. data/test/regression/xlsx_files/chart_axis02.xlsx +0 -0
  405. data/test/regression/xlsx_files/chart_axis03.xlsx +0 -0
  406. data/test/regression/xlsx_files/chart_axis04.xlsx +0 -0
  407. data/test/regression/xlsx_files/chart_axis05.xlsx +0 -0
  408. data/test/regression/xlsx_files/chart_axis06.xlsx +0 -0
  409. data/test/regression/xlsx_files/chart_axis07.xlsx +0 -0
  410. data/test/regression/xlsx_files/chart_axis08.xlsx +0 -0
  411. data/test/regression/xlsx_files/chart_axis09.xlsx +0 -0
  412. data/test/regression/xlsx_files/chart_axis10.xlsx +0 -0
  413. data/test/regression/xlsx_files/chart_axis11.xlsx +0 -0
  414. data/test/regression/xlsx_files/chart_axis12.xlsx +0 -0
  415. data/test/regression/xlsx_files/chart_axis13.xlsx +0 -0
  416. data/test/regression/xlsx_files/chart_axis14.xlsx +0 -0
  417. data/test/regression/xlsx_files/chart_axis15.xlsx +0 -0
  418. data/test/regression/xlsx_files/chart_axis16.xlsx +0 -0
  419. data/test/regression/xlsx_files/chart_axis17.xlsx +0 -0
  420. data/test/regression/xlsx_files/chart_axis18.xlsx +0 -0
  421. data/test/regression/xlsx_files/chart_axis19.xlsx +0 -0
  422. data/test/regression/xlsx_files/chart_axis20.xlsx +0 -0
  423. data/test/regression/xlsx_files/chart_axis21.xlsx +0 -0
  424. data/test/regression/xlsx_files/chart_bar01.xlsx +0 -0
  425. data/test/regression/xlsx_files/chart_bar02.xlsx +0 -0
  426. data/test/regression/xlsx_files/chart_bar03.xlsx +0 -0
  427. data/test/regression/xlsx_files/chart_bar04.xlsx +0 -0
  428. data/test/regression/xlsx_files/chart_bar05.xlsx +0 -0
  429. data/test/regression/xlsx_files/chart_bar06.xlsx +0 -0
  430. data/test/regression/xlsx_files/chart_bar07.xlsx +0 -0
  431. data/test/regression/xlsx_files/chart_bar08.xlsx +0 -0
  432. data/test/regression/xlsx_files/chart_bar09.xlsx +0 -0
  433. data/test/regression/xlsx_files/chart_bar10.xlsx +0 -0
  434. data/test/regression/xlsx_files/chart_bar11.xlsx +0 -0
  435. data/test/regression/xlsx_files/chart_bar12.xlsx +0 -0
  436. data/test/regression/xlsx_files/chart_bar13.xlsx +0 -0
  437. data/test/regression/xlsx_files/chart_bar14.xlsx +0 -0
  438. data/test/regression/xlsx_files/chart_bar15.xlsx +0 -0
  439. data/test/regression/xlsx_files/chart_bar16.xlsx +0 -0
  440. data/test/regression/xlsx_files/chart_bar17.xlsx +0 -0
  441. data/test/regression/xlsx_files/chart_bar18.xlsx +0 -0
  442. data/test/regression/xlsx_files/chart_bar19.xlsx +0 -0
  443. data/test/regression/xlsx_files/chart_bar20.xlsx +0 -0
  444. data/test/regression/xlsx_files/chart_bar21.xlsx +0 -0
  445. data/test/regression/xlsx_files/chart_bar22.xlsx +0 -0
  446. data/test/regression/xlsx_files/chart_bar23.xlsx +0 -0
  447. data/test/regression/xlsx_files/chart_bar24.xlsx +0 -0
  448. data/test/regression/xlsx_files/chart_blank01.xlsx +0 -0
  449. data/test/regression/xlsx_files/chart_blank02.xlsx +0 -0
  450. data/test/regression/xlsx_files/chart_blank03.xlsx +0 -0
  451. data/test/regression/xlsx_files/chart_blank04.xlsx +0 -0
  452. data/test/regression/xlsx_files/chart_blank05.xlsx +0 -0
  453. data/test/regression/xlsx_files/chart_blank06.xlsx +0 -0
  454. data/test/regression/xlsx_files/chart_column01.xlsx +0 -0
  455. data/test/regression/xlsx_files/chart_column02.xlsx +0 -0
  456. data/test/regression/xlsx_files/chart_column03.xlsx +0 -0
  457. data/test/regression/xlsx_files/chart_column04.xlsx +0 -0
  458. data/test/regression/xlsx_files/chart_column05.xlsx +0 -0
  459. data/test/regression/xlsx_files/chart_column06.xlsx +0 -0
  460. data/test/regression/xlsx_files/chart_crossing01.xlsx +0 -0
  461. data/test/regression/xlsx_files/chart_crossing02.xlsx +0 -0
  462. data/test/regression/xlsx_files/chart_crossing03.xlsx +0 -0
  463. data/test/regression/xlsx_files/chart_crossing04.xlsx +0 -0
  464. data/test/regression/xlsx_files/chart_format01.xlsx +0 -0
  465. data/test/regression/xlsx_files/chart_format02.xlsx +0 -0
  466. data/test/regression/xlsx_files/chart_format03.xlsx +0 -0
  467. data/test/regression/xlsx_files/chart_format04.xlsx +0 -0
  468. data/test/regression/xlsx_files/chart_format05.xlsx +0 -0
  469. data/test/regression/xlsx_files/chart_format06.xlsx +0 -0
  470. data/test/regression/xlsx_files/chart_format07.xlsx +0 -0
  471. data/test/regression/xlsx_files/chart_format08.xlsx +0 -0
  472. data/test/regression/xlsx_files/chart_format09.xlsx +0 -0
  473. data/test/regression/xlsx_files/chart_format10.xlsx +0 -0
  474. data/test/regression/xlsx_files/chart_format11.xlsx +0 -0
  475. data/test/regression/xlsx_files/chart_format12.xlsx +0 -0
  476. data/test/regression/xlsx_files/chart_format13.xlsx +0 -0
  477. data/test/regression/xlsx_files/chart_format14.xlsx +0 -0
  478. data/test/regression/xlsx_files/chart_format15.xlsx +0 -0
  479. data/test/regression/xlsx_files/chart_format16.xlsx +0 -0
  480. data/test/regression/xlsx_files/chart_format17.xlsx +0 -0
  481. data/test/regression/xlsx_files/chart_format18.xlsx +0 -0
  482. data/test/regression/xlsx_files/chart_line01.xlsx +0 -0
  483. data/test/regression/xlsx_files/chart_line02.xlsx +0 -0
  484. data/test/regression/xlsx_files/chart_name01.xlsx +0 -0
  485. data/test/regression/xlsx_files/chart_name02.xlsx +0 -0
  486. data/test/regression/xlsx_files/chart_name03.xlsx +0 -0
  487. data/test/regression/xlsx_files/chart_pie01.xlsx +0 -0
  488. data/test/regression/xlsx_files/chart_scatter01.xlsx +0 -0
  489. data/test/regression/xlsx_files/chart_scatter02.xlsx +0 -0
  490. data/test/regression/xlsx_files/chart_scatter03.xlsx +0 -0
  491. data/test/regression/xlsx_files/chart_scatter04.xlsx +0 -0
  492. data/test/regression/xlsx_files/chart_scatter05.xlsx +0 -0
  493. data/test/regression/xlsx_files/chart_scatter06.xlsx +0 -0
  494. data/test/regression/xlsx_files/chart_scatter07.xlsx +0 -0
  495. data/test/regression/xlsx_files/chart_sparse01.xlsx +0 -0
  496. data/test/regression/xlsx_files/chart_stock01.xlsx +0 -0
  497. data/test/regression/xlsx_files/chart_stock02.xlsx +0 -0
  498. data/test/regression/xlsx_files/chart_str01.xlsx +0 -0
  499. data/test/regression/xlsx_files/chart_str02.xlsx +0 -0
  500. data/test/regression/xlsx_files/chartsheet01.xlsx +0 -0
  501. data/test/regression/xlsx_files/chartsheet02.xlsx +0 -0
  502. data/test/regression/xlsx_files/chartsheet03.xlsx +0 -0
  503. data/test/regression/xlsx_files/chartsheet04.xlsx +0 -0
  504. data/test/regression/xlsx_files/chartsheet05.xlsx +0 -0
  505. data/test/regression/xlsx_files/chartsheet06.xlsx +0 -0
  506. data/test/regression/xlsx_files/chartsheet07.xlsx +0 -0
  507. data/test/regression/xlsx_files/chartsheet08.xlsx +0 -0
  508. data/test/regression/xlsx_files/chartsheet09.xlsx +0 -0
  509. data/test/regression/xlsx_files/comment01.xlsx +0 -0
  510. data/test/regression/xlsx_files/comment02.xlsx +0 -0
  511. data/test/regression/xlsx_files/comment03.xlsx +0 -0
  512. data/test/regression/xlsx_files/comment04.xlsx +0 -0
  513. data/test/regression/xlsx_files/comment05.xlsx +0 -0
  514. data/test/regression/xlsx_files/comment06.xlsx +0 -0
  515. data/test/regression/xlsx_files/comment07.xlsx +0 -0
  516. data/test/regression/xlsx_files/comment08.xlsx +0 -0
  517. data/test/regression/xlsx_files/comment09.xlsx +0 -0
  518. data/test/regression/xlsx_files/comment10.xlsx +0 -0
  519. data/test/regression/xlsx_files/cond_format01.xlsx +0 -0
  520. data/test/regression/xlsx_files/cond_format02.xlsx +0 -0
  521. data/test/regression/xlsx_files/cond_format03.xlsx +0 -0
  522. data/test/regression/xlsx_files/cond_format04.xlsx +0 -0
  523. data/test/regression/xlsx_files/cond_format05.xlsx +0 -0
  524. data/test/regression/xlsx_files/cond_format06.xlsx +0 -0
  525. data/test/regression/xlsx_files/cond_format07.xlsx +0 -0
  526. data/test/regression/xlsx_files/cond_format08.xlsx +0 -0
  527. data/test/regression/xlsx_files/cond_format10.xlsx +0 -0
  528. data/test/regression/xlsx_files/cond_format11.xlsx +0 -0
  529. data/test/regression/xlsx_files/cond_format12.xlsx +0 -0
  530. data/test/regression/xlsx_files/custom_colors01.xlsx +0 -0
  531. data/test/regression/xlsx_files/date_1904_01.xlsx +0 -0
  532. data/test/regression/xlsx_files/date_1904_02.xlsx +0 -0
  533. data/test/regression/xlsx_files/defined_name01.xlsx +0 -0
  534. data/test/regression/xlsx_files/escapes01.xlsx +0 -0
  535. data/test/regression/xlsx_files/escapes02.xlsx +0 -0
  536. data/test/regression/xlsx_files/escapes03.xlsx +0 -0
  537. data/test/regression/xlsx_files/filehandle01.xlsx +0 -0
  538. data/test/regression/xlsx_files/fit_to_pages01.xlsx +0 -0
  539. data/test/regression/xlsx_files/fit_to_pages02.xlsx +0 -0
  540. data/test/regression/xlsx_files/fit_to_pages03.xlsx +0 -0
  541. data/test/regression/xlsx_files/fit_to_pages04.xlsx +0 -0
  542. data/test/regression/xlsx_files/fit_to_pages05.xlsx +0 -0
  543. data/test/regression/xlsx_files/format01.xlsx +0 -0
  544. data/test/regression/xlsx_files/format02.xlsx +0 -0
  545. data/test/regression/xlsx_files/format03.xlsx +0 -0
  546. data/test/regression/xlsx_files/format04.xlsx +0 -0
  547. data/test/regression/xlsx_files/gridlines01.xlsx +0 -0
  548. data/test/regression/xlsx_files/hyperlink01.xlsx +0 -0
  549. data/test/regression/xlsx_files/hyperlink02.xlsx +0 -0
  550. data/test/regression/xlsx_files/hyperlink03.xlsx +0 -0
  551. data/test/regression/xlsx_files/hyperlink04.xlsx +0 -0
  552. data/test/regression/xlsx_files/hyperlink05.xlsx +0 -0
  553. data/test/regression/xlsx_files/hyperlink06.xlsx +0 -0
  554. data/test/regression/xlsx_files/hyperlink07.xlsx +0 -0
  555. data/test/regression/xlsx_files/hyperlink08.xlsx +0 -0
  556. data/test/regression/xlsx_files/hyperlink09.xlsx +0 -0
  557. data/test/regression/xlsx_files/hyperlink10.xlsx +0 -0
  558. data/test/regression/xlsx_files/hyperlink11.xlsx +0 -0
  559. data/test/regression/xlsx_files/hyperlink12.xlsx +0 -0
  560. data/test/regression/xlsx_files/hyperlink13.xlsx +0 -0
  561. data/test/regression/xlsx_files/hyperlink14.xlsx +0 -0
  562. data/test/regression/xlsx_files/hyperlink15.xlsx +0 -0
  563. data/test/regression/xlsx_files/hyperlink16.xlsx +0 -0
  564. data/test/regression/xlsx_files/hyperlink17.xlsx +0 -0
  565. data/test/regression/xlsx_files/hyperlink18.xlsx +0 -0
  566. data/test/regression/xlsx_files/image01.xlsx +0 -0
  567. data/test/regression/xlsx_files/image02.xlsx +0 -0
  568. data/test/regression/xlsx_files/image03.xlsx +0 -0
  569. data/test/regression/xlsx_files/image04.xlsx +0 -0
  570. data/test/regression/xlsx_files/image05.xlsx +0 -0
  571. data/test/regression/xlsx_files/image06.xlsx +0 -0
  572. data/test/regression/xlsx_files/image07.xlsx +0 -0
  573. data/test/regression/xlsx_files/outline01.xlsx +0 -0
  574. data/test/regression/xlsx_files/outline02.xlsx +0 -0
  575. data/test/regression/xlsx_files/outline03.xlsx +0 -0
  576. data/test/regression/xlsx_files/outline04.xlsx +0 -0
  577. data/test/regression/xlsx_files/outline05.xlsx +0 -0
  578. data/test/regression/xlsx_files/outline06.xlsx +0 -0
  579. data/test/regression/xlsx_files/page_breaks01.xlsx +0 -0
  580. data/test/regression/xlsx_files/page_breaks02.xlsx +0 -0
  581. data/test/regression/xlsx_files/page_breaks03.xlsx +0 -0
  582. data/test/regression/xlsx_files/page_breaks04.xlsx +0 -0
  583. data/test/regression/xlsx_files/page_breaks05.xlsx +0 -0
  584. data/test/regression/xlsx_files/page_breaks06.xlsx +0 -0
  585. data/test/regression/xlsx_files/page_view01.xlsx +0 -0
  586. data/test/regression/xlsx_files/panes01.xlsx +0 -0
  587. data/test/regression/xlsx_files/print_across01.xlsx +0 -0
  588. data/test/regression/xlsx_files/print_area01.xlsx +0 -0
  589. data/test/regression/xlsx_files/print_area02.xlsx +0 -0
  590. data/test/regression/xlsx_files/print_area03.xlsx +0 -0
  591. data/test/regression/xlsx_files/print_area04.xlsx +0 -0
  592. data/test/regression/xlsx_files/print_area05.xlsx +0 -0
  593. data/test/regression/xlsx_files/print_area06.xlsx +0 -0
  594. data/test/regression/xlsx_files/print_area07.xlsx +0 -0
  595. data/test/regression/xlsx_files/print_options01.xlsx +0 -0
  596. data/test/regression/xlsx_files/print_options02.xlsx +0 -0
  597. data/test/regression/xlsx_files/print_options03.xlsx +0 -0
  598. data/test/regression/xlsx_files/print_options04.xlsx +0 -0
  599. data/test/regression/xlsx_files/print_options05.xlsx +0 -0
  600. data/test/regression/xlsx_files/print_options06.xlsx +0 -0
  601. data/test/regression/xlsx_files/print_scale01.xlsx +0 -0
  602. data/test/regression/xlsx_files/print_scale02.xlsx +0 -0
  603. data/test/regression/xlsx_files/properties01.xlsx +0 -0
  604. data/test/regression/xlsx_files/repeat01.xlsx +0 -0
  605. data/test/regression/xlsx_files/repeat02.xlsx +0 -0
  606. data/test/regression/xlsx_files/repeat03.xlsx +0 -0
  607. data/test/regression/xlsx_files/repeat04.xlsx +0 -0
  608. data/test/regression/xlsx_files/repeat05.xlsx +0 -0
  609. data/test/regression/xlsx_files/rich_string01.xlsx +0 -0
  610. data/test/regression/xlsx_files/rich_string02.xlsx +0 -0
  611. data/test/regression/xlsx_files/rich_string03.xlsx +0 -0
  612. data/test/regression/xlsx_files/rich_string04.xlsx +0 -0
  613. data/test/regression/xlsx_files/rich_string05.xlsx +0 -0
  614. data/test/regression/xlsx_files/rich_string06.xlsx +0 -0
  615. data/test/regression/xlsx_files/rich_string07.xlsx +0 -0
  616. data/test/regression/xlsx_files/rich_string08.xlsx +0 -0
  617. data/test/regression/xlsx_files/rich_string09.xlsx +0 -0
  618. data/test/regression/xlsx_files/rich_string10.xlsx +0 -0
  619. data/test/regression/xlsx_files/rich_string11.xlsx +0 -0
  620. data/test/regression/xlsx_files/row_col_format01.xlsx +0 -0
  621. data/test/regression/xlsx_files/row_col_format02.xlsx +0 -0
  622. data/test/regression/xlsx_files/row_col_format03.xlsx +0 -0
  623. data/test/regression/xlsx_files/row_col_format04.xlsx +0 -0
  624. data/test/regression/xlsx_files/row_col_format05.xlsx +0 -0
  625. data/test/regression/xlsx_files/row_col_format06.xlsx +0 -0
  626. data/test/regression/xlsx_files/row_col_format07.xlsx +0 -0
  627. data/test/regression/xlsx_files/row_col_format08.xlsx +0 -0
  628. data/test/regression/xlsx_files/row_col_format09.xlsx +0 -0
  629. data/test/regression/xlsx_files/row_col_format10.xlsx +0 -0
  630. data/test/regression/xlsx_files/row_col_format11.xlsx +0 -0
  631. data/test/regression/xlsx_files/row_col_format12.xlsx +0 -0
  632. data/test/regression/xlsx_files/row_col_format13.xlsx +0 -0
  633. data/test/regression/xlsx_files/row_col_format14.xlsx +0 -0
  634. data/test/regression/xlsx_files/shape_connect01.xlsx +0 -0
  635. data/test/regression/xlsx_files/shape_connect02.xlsx +0 -0
  636. data/test/regression/xlsx_files/shape_connect03.xlsx +0 -0
  637. data/test/regression/xlsx_files/shape_connect04.xlsx +0 -0
  638. data/test/regression/xlsx_files/shape_scale01.xlsx +0 -0
  639. data/test/regression/xlsx_files/shape_stencil01.xlsx +0 -0
  640. data/test/regression/xlsx_files/shared_strings01.xlsx +0 -0
  641. data/test/regression/xlsx_files/shared_strings02.xlsx +0 -0
  642. data/test/regression/xlsx_files/simple01.xlsx +0 -0
  643. data/test/regression/xlsx_files/simple02.xlsx +0 -0
  644. data/test/regression/xlsx_files/tab_color01.xlsx +0 -0
  645. data/test/regression/xlsx_files/table01.xlsx +0 -0
  646. data/test/regression/xlsx_files/table02.xlsx +0 -0
  647. data/test/regression/xlsx_files/table03.xlsx +0 -0
  648. data/test/regression/xlsx_files/table04.xlsx +0 -0
  649. data/test/regression/xlsx_files/table05.xlsx +0 -0
  650. data/test/regression/xlsx_files/table06.xlsx +0 -0
  651. data/test/regression/xlsx_files/table07.xlsx +0 -0
  652. data/test/regression/xlsx_files/table08.xlsx +0 -0
  653. data/test/regression/xlsx_files/table09.xlsx +0 -0
  654. data/test/regression/xlsx_files/table10.xlsx +0 -0
  655. data/test/regression/xlsx_files/table11.xlsx +0 -0
  656. data/test/regression/xlsx_files/table12.xlsx +0 -0
  657. data/test/regression/xlsx_files/table13.xlsx +0 -0
  658. data/test/regression/xlsx_files/table14.xlsx +0 -0
  659. data/test/test_example_match.rb +2386 -889
  660. data/test/workbook/test_write_defined_names.rb +1 -1
  661. data/test/worksheet/test_cond_format_01.rb +82 -0
  662. data/test/worksheet/test_cond_format_02.rb +87 -0
  663. data/test/worksheet/test_cond_format_03.rb +97 -0
  664. data/test/worksheet/test_cond_format_04.rb +85 -0
  665. data/test/worksheet/test_cond_format_05.rb +96 -0
  666. data/test/worksheet/test_cond_format_06.rb +106 -0
  667. data/test/worksheet/test_cond_format_07.rb +116 -0
  668. data/test/worksheet/test_cond_format_08.rb +115 -0
  669. data/test/worksheet/test_cond_format_09.rb +108 -0
  670. data/test/worksheet/test_cond_format_10.rb +83 -0
  671. data/test/worksheet/test_cond_format_11.rb +85 -0
  672. data/test/worksheet/test_cond_format_12.rb +133 -0
  673. data/test/worksheet/test_cond_format_13.rb +135 -0
  674. data/test/worksheet/test_cond_format_14.rb +132 -0
  675. data/test/worksheet/test_cond_format_15.rb +93 -0
  676. data/test/worksheet/test_cond_format_16.rb +138 -0
  677. data/test/worksheet/test_cond_format_17.rb +141 -0
  678. data/test/worksheet/test_cond_format_18.rb +135 -0
  679. data/test/worksheet/test_cond_format_19.rb +139 -0
  680. data/test/worksheet/test_write_array_formula_01.rb +3 -4
  681. data/test/worksheet/test_write_data_validation_01.rb +1 -1
  682. data/test/worksheet/test_write_data_validation_02.rb +2 -2
  683. data/test/worksheet/test_write_methods.rb +6 -1
  684. data/test/worksheet/test_write_page_setup.rb +1 -1
  685. data/test/worksheet/test_write_sheet_view.rb +1 -1
  686. data/write_xlsx.gemspec +644 -9
  687. metadata +649 -22
  688. data/test/chart/test_write_chart_space.rb +0 -15
@@ -158,5 +158,25 @@ def underline_attributes(underline)
158
158
  [] # Default to single underline.
159
159
  end
160
160
  end
161
+
162
+ #
163
+ # return perl's boolean result
164
+ #
165
+ def ptrue?(value)
166
+ if [false, nil, 0, "0", "", [], {}].include?(value)
167
+ false
168
+ else
169
+ true
170
+ end
171
+ end
172
+
173
+ def check_parameter(params, valid_keys, method)
174
+ invalids = params.keys - valid_keys
175
+ unless invalids.empty?
176
+ raise WriteXLSXOptionParameterError,
177
+ "Unknown parameter '#{invalids.join(', ')}' in #{method}."
178
+ end
179
+ true
180
+ end
161
181
  end
162
182
  end
@@ -2,7 +2,9 @@
2
2
  require 'write_xlsx/package/xml_writer_simple'
3
3
  require 'write_xlsx/package/packager'
4
4
  require 'write_xlsx/worksheet'
5
+ require 'write_xlsx/chartsheet'
5
6
  require 'write_xlsx/format'
7
+ require 'write_xlsx/shape'
6
8
  require 'write_xlsx/utility'
7
9
  require 'write_xlsx/chart'
8
10
  require 'write_xlsx/zip_file_utils'
@@ -22,10 +24,10 @@ class Workbook
22
24
  attr_reader :doc_properties
23
25
  attr_reader :image_types, :images
24
26
  attr_reader :shared_strings
25
-
27
+ attr_accessor :table_count
26
28
  #
27
- # A new Excel workbook is created using the new() constructor which accepts either a filename
28
- # or a IO object as a parameter.
29
+ # A new Excel workbook is created using the new() constructor
30
+ # which accepts either a filename or an IO object as a parameter.
29
31
  # The following example creates a new Excel file based on a filename:
30
32
  #
31
33
  # workbook = WriteXLSX.new('filename.xlsx')
@@ -40,15 +42,16 @@ class Workbook
40
42
  # workbook3 = WriteXLSX.new("c:\\tmp\\filename.xlsx")
41
43
  # workbook4 = WriteXLSX.new('c:\tmp\filename.xlsx')
42
44
  #
43
- # The last two examples demonstrates how to create a file on DOS or Windows where it is
44
- # necessary to either escape the directory separator \ or to use single quotes to ensure
45
- # that it isn't interpolated.
45
+ # The last two examples demonstrates how to create a file on DOS or Windows
46
+ # where it is necessary to either escape the directory separator \
47
+ # or to use single quotes to ensure that it isn't interpolated.
46
48
  #
47
- # It is recommended that the filename uses the extension .xlsx rather than .xls since
48
- # the latter causes an Excel warning when used with the XLSX format.
49
+ # It is recommended that the filename uses the extension .xlsx
50
+ # rather than .xls since the latter causes an Excel warning
51
+ # when used with the XLSX format.
49
52
  #
50
- # The new() constructor returns a WriteXLSX object that you can use to add worksheets and
51
- # store data.
53
+ # The new() constructor returns a WriteXLSX object that you can use to
54
+ # add worksheets and store data.
52
55
  #
53
56
  # You can also pass a valid IO object to the new() constructor.
54
57
  #
@@ -97,8 +100,16 @@ def initialize(file, default_formats = {})
97
100
  @doc_properties = {}
98
101
  @local_time = Time.now
99
102
  @num_comment_files = 0
103
+ @optimization = 0
104
+ @x_window = 240
105
+ @y_window = 15
106
+ @window_width = 16095
107
+ @window_height = 9660
108
+ @tab_ratio = 500
109
+ @table_count = 0
100
110
  @image_types = {}
101
111
  @images = []
112
+ @images_seen = {}
102
113
 
103
114
  # Structures for the shared strings data.
104
115
  @shared_strings = Package::SharedStrings.new
@@ -114,7 +125,7 @@ def close
114
125
  # In case close() is called twice, by user and by DESTROY.
115
126
  return if @fileclosed
116
127
 
117
- @fileclosed = 1
128
+ @fileclosed = true
118
129
  store_workbook
119
130
  end
120
131
 
@@ -179,7 +190,7 @@ def set_1904(mode = true)
179
190
  unless sheets.empty?
180
191
  raise "set_1904() must be called before add_worksheet()"
181
192
  end
182
- @date_1904 = (!mode || mode == 0) ? false : true
193
+ @date_1904 = ptrue?(mode)
183
194
  end
184
195
 
185
196
  def get_1904
@@ -261,20 +272,17 @@ def assemble_xml_file #:nodoc:
261
272
  # sheetname for more than one worksheet.
262
273
  #
263
274
  def add_worksheet(name = '')
264
- index = @worksheets.size
265
275
  name = check_sheetname(name)
266
-
267
- worksheet = Worksheet.new(self, index, name)
268
- @worksheets[index] = worksheet
269
- @sheetnames[index] = name
270
-
276
+ worksheet = Worksheet.new(self, @worksheets.size, name)
277
+ @worksheets << worksheet
278
+ @sheetnames << name
271
279
  worksheet
272
280
  end
273
281
 
274
282
  #
275
283
  # This method is use to create a new chart either as a standalone worksheet
276
284
  # (the default) or as an embeddable object that can be inserted into
277
- # a worksheet via the insert_chart() Worksheet method.
285
+ # a worksheet via the Worksheet#insert_chart method.
278
286
  #
279
287
  # chart = workbook.add_chart(:type => 'column')
280
288
  #
@@ -287,7 +295,8 @@ def add_worksheet(name = '')
287
295
  #
288
296
  # :type
289
297
  #
290
- # This is a required parameter. It defines the type of chart that will be created.
298
+ # This is a required parameter.
299
+ # It defines the type of chart that will be created.
291
300
  #
292
301
  # chart = workbook.add_chart(:type => 'line')
293
302
  #
@@ -315,15 +324,16 @@ def add_worksheet(name = '')
315
324
  #
316
325
  # Set the name for the chart sheet. The name property is optional and
317
326
  # if it isn't supplied will default to Chart1 .. n. The name must be
318
- # a valid Excel worksheet name. See add_worksheet for more details on
319
- # valid sheet names. The name property can be omitted for embedded charts.
327
+ # a valid Excel worksheet name. See add_worksheet
328
+ # for more details on valid sheet names. The name property can be
329
+ # omitted for embedded charts.
320
330
  #
321
331
  # chart = workbook.add_chart(:type => 'line', :name => 'Results Chart')
322
332
  #
323
333
  # :embedded
324
334
  #
325
335
  # Specifies that the Chart object will be inserted in a worksheet
326
- # via the insert_chart Worksheet method. It is an error to try insert
336
+ # via the Worksheet#insert_chart method. It is an error to try insert
327
337
  # a Chart that doesn't have this flag set.
328
338
  #
329
339
  # chart = workbook.add_chart(:type => 'line', :embedded => 1)
@@ -339,46 +349,36 @@ def add_worksheet(name = '')
339
349
  # directory of the distro.
340
350
  #
341
351
  def add_chart(params = {})
342
- name = ''
343
- index = @worksheets.size
344
-
345
352
  # Type must be specified so we can create the required chart instance.
346
- type = params[:type]
353
+ type = params[:type]
354
+ embedded = params[:embedded]
355
+ name = params[:name]
347
356
  raise "Must define chart type in add_chart()" unless type
348
357
 
349
- # Ensure that the chart defaults to non embedded.
350
- embedded = params[:embedded] || 0
351
-
352
- # Check the worksheet name for non-embedded charts.
353
- name = check_sheetname(params[:name], 1) unless embedded
354
-
355
- chart = Chart.factory(type)
358
+ chart = Chart.factory(type, params[:subtype])
359
+ chart.palette = @palette
356
360
 
357
361
  # Get an incremental id to use for axes ids.
358
362
  chart.id = @charts.size
359
363
 
360
364
  # If the chart isn't embedded let the workbook control it.
361
- if embedded
365
+ if ptrue?(embedded)
366
+ chart.name = name if name
367
+
362
368
  # Set index to 0 so that the activate() and set_first_sheet() methods
363
369
  # point back to the first worksheet if used for embedded charts.
364
370
  chart.index = 0
365
- chart.palette = @palette
366
371
  chart.set_embedded_config_data
367
- @charts << chart
368
-
369
- return chart
370
372
  else
371
- chartsheet = Chartsheet.new(self, name, index)
372
- chart.palette = @palette
373
+ # Check the worksheet name for non-embedded charts.
374
+ sheetname = check_chart_sheetname(name)
375
+ chartsheet = Chartsheet.new(self, @worksheets.size, sheetname)
373
376
  chartsheet.chart = chart
374
- chartsheet.drawing = Drawing.new
375
- @worksheets.index = chartsheet
376
- @sheetnames.index = name
377
-
378
- @charts << chart
379
-
380
- return chartsheet
377
+ @worksheets << chartsheet
378
+ @sheetnames << sheetname
381
379
  end
380
+ @charts << chart
381
+ ptrue?(embedded) ? chart : chartsheet
382
382
  end
383
383
 
384
384
  #
@@ -406,14 +406,246 @@ def add_format(properties = {})
406
406
  format
407
407
  end
408
408
 
409
+ #
410
+ # The add_shape() method can be used to create new shapes that may be
411
+ # inserted into a worksheet.
412
+ #
413
+ # You can either define the properties at creation time via a hash of
414
+ # property values or later via method calls.
415
+ #
416
+ # # Set properties at creation.
417
+ # plus = workbook.add_shape(
418
+ # :type => 'plus',
419
+ # :id => 3,
420
+ # :width => pw,
421
+ # :height => ph
422
+ # )
423
+ #
424
+ # # Default rectangle shape. Set properties later.
425
+ # rect = workbook.add_shape
426
+ #
427
+ # See also the shape*.rb programs in the examples directory of the distro.
428
+ #
429
+ # === Shape Properties
430
+ #
431
+ # Any shape property can be queried or modified by [] like hash.
432
+ #
433
+ # ellipse = workbook.add_shape(properties)
434
+ # ellipse[:type] = 'cross' # No longer an ellipse !
435
+ # type = ellipse[:type] # Find out what it really is.
436
+ #
437
+ # The properties of a shape object that can be defined via add_shape are
438
+ # shown below.
439
+ #
440
+ # ====:name
441
+ #
442
+ # Defines the name of the shape. This is an optional property and the shape
443
+ # will be given a default name if not supplied. The name is generally only
444
+ # used by Excel Macros to refer to the object.
445
+ #
446
+ # ====:type
447
+ #
448
+ # Defines the type of the object such as :rect, :ellipse OR :triangle.
449
+ #
450
+ # ellipse = workbook.add_shape(:type => :ellipse)
451
+ #
452
+ # The default type is :rect.
453
+ #
454
+ # The full list of available shapes is shown below.
455
+ #
456
+ # See also the shape_all.rb program in the examples directory of the distro.
457
+ # It creates an example workbook with all supported shapes labelled with
458
+ # their shape names.
459
+ #
460
+ # ===== Basic Shapes
461
+ #
462
+ # blockArc can chevron cube decagon
463
+ # diamond dodecagon donut ellipse funnel
464
+ # gear6 gear9 heart heptagon hexagon
465
+ # homePlate lightningBolt line lineInv moon
466
+ # nonIsoscelesTrapezoid noSmoking octagon parallelogram pentagon
467
+ # pie pieWedge plaque rect round1Rect
468
+ # round2DiagRect round2SameRect roundRect rtTriangle smileyFace
469
+ # snip1Rect snip2DiagRect snip2SameRect snipRoundRect star10
470
+ # star12 star16 star24 star32 star4
471
+ # star5 star6 star7 star8 sun
472
+ # teardrop trapezoid triangle
473
+ #
474
+ # ===== Arrow Shapes
475
+ #
476
+ # bentArrow bentUpArrow circularArrow curvedDownArrow
477
+ # curvedLeftArrow curvedRightArrow curvedUpArrow downArrow
478
+ # leftArrow leftCircularArrow leftRightArrow leftRightCircularArrow
479
+ # leftRightUpArrow leftUpArrow notchedRightArrow quadArrow
480
+ # rightArrow stripedRightArrow swooshArrow upArrow
481
+ # upDownArrow uturnArrow
482
+ #
483
+ # ===== Connector Shapes
484
+ #
485
+ # bentConnector2 bentConnector3 bentConnector4
486
+ # bentConnector5 curvedConnector2 curvedConnector3
487
+ # curvedConnector4 curvedConnector5 straightConnector1
488
+ #
489
+ # ===== Callout Shapes
490
+ #
491
+ # accentBorderCallout1 accentBorderCallout2 accentBorderCallout3
492
+ # accentCallout1 accentCallout2 accentCallout3
493
+ # borderCallout1 borderCallout2 borderCallout3
494
+ # callout1 callout2 callout3
495
+ # cloudCallout downArrowCallout leftArrowCallout
496
+ # leftRightArrowCallout quadArrowCallout rightArrowCallout
497
+ # upArrowCallout upDownArrowCallout wedgeEllipseCallout
498
+ # wedgeRectCallout wedgeRoundRectCallout
499
+ #
500
+ # ===== Flow Chart Shapes
501
+ #
502
+ # flowChartAlternateProcess flowChartCollate flowChartConnector
503
+ # flowChartDecision flowChartDelay flowChartDisplay
504
+ # flowChartDocument flowChartExtract flowChartInputOutput
505
+ # flowChartInternalStorage flowChartMagneticDisk flowChartMagneticDrum
506
+ # flowChartMagneticTape flowChartManualInput flowChartManualOperation
507
+ # flowChartMerge flowChartMultidocument flowChartOfflineStorage
508
+ # flowChartOffpageConnector flowChartOnlineStorage flowChartOr
509
+ # flowChartPredefinedProcess flowChartPreparation flowChartProcess
510
+ # flowChartPunchedCard flowChartPunchedTape flowChartSort
511
+ # flowChartSummingJunction flowChartTerminator
512
+ #
513
+ # ===== Action Shapes
514
+ #
515
+ # actionButtonBackPrevious actionButtonBeginning actionButtonBlank
516
+ # actionButtonDocument actionButtonEnd actionButtonForwardNext
517
+ # actionButtonHelp actionButtonHome actionButtonInformation
518
+ # actionButtonMovie actionButtonReturn actionButtonSound
519
+ #
520
+ # ===== Chart Shapes
521
+ #
522
+ # Not to be confused with Excel Charts.
523
+ #
524
+ # chartPlus chartStar chartX
525
+ #
526
+ # ===== Math Shapes
527
+ #
528
+ # mathDivide mathEqual mathMinus mathMultiply mathNotEqual mathPlus
529
+ #
530
+ # ===== Starts and Banners
531
+ #
532
+ # arc bevel bracePair bracketPair chord
533
+ # cloud corner diagStripe doubleWave ellipseRibbon
534
+ # ellipseRibbon2 foldedCorner frame halfFrame horizontalScroll
535
+ # irregularSeal1 irregularSeal2 leftBrace leftBracket leftRightRibbon
536
+ # plus ribbon ribbon2 rightBrace rightBracket
537
+ # verticalScroll wave
538
+ #
539
+ # ===== Tab Shapes
540
+ #
541
+ # cornerTabs plaqueTabs squareTabs
542
+ #
543
+ # ==== :text
544
+ #
545
+ # This property is used to make the shape act like a text box.
546
+ #
547
+ # rect = workbook.add_shape(:type => 'rect', :text => "Hello \nWorld")
548
+ #
549
+ # The Text is super-imposed over the shape. The text can be wrapped using
550
+ # the newline character \n.
551
+ #
552
+ # ==== :id
553
+ #
554
+ # Identification number for internal identification. This number will be
555
+ # auto-assigned, if not assigned, or if it is a duplicate.
556
+ #
557
+ # ==== :format
558
+ #
559
+ # Workbook format for decorating the shape horizontally and/or vertically.
560
+ #
561
+ # ==== :rotation
562
+ #
563
+ # Shape rotation, in degrees, from 0 to 360
564
+ #
565
+ # ==== :line, :fill
566
+ #
567
+ # Shape color for the outline and fill.
568
+ # Colors may be specified as a color index, or in RGB format, i.e. AA00FF.
569
+ #
570
+ # ==== :link_type
571
+ #
572
+ # Line type for shape outline. The default is solid.
573
+ # The list of possible values is:
574
+ #
575
+ # dash, sysDot, dashDot, lgDash, lgDashDot, lgDashDotDot, solid
576
+ #
577
+ # ==== :valign, :align
578
+ #
579
+ # Text alignment within the shape.
580
+ #
581
+ # Vertical alignment can be:
582
+ #
583
+ # Setting Meaning
584
+ # ======= =======
585
+ # t Top
586
+ # ctr Centre
587
+ # b Bottom def add_shape(properties)
588
+ #
589
+ # The default is to center both horizontally and vertically.
590
+ #
591
+ # ==== :scale_x, :scale_y
592
+ #
593
+ #
594
+ # Scale factor in x and y dimension, for scaling the shape width and height. The default value is 1.
595
+ #
596
+ # Scaling may be set on the shape object or via insert_shape().
597
+ #
598
+ # ==== :adjustments
599
+ #
600
+ # Adjustment of shape vertices. Most shapes do not use this. For some
601
+ # shapes, there is a single adjustment to modify the geometry.
602
+ # For instance, the plus shape has one adjustment to control the width
603
+ # of the spokes.
604
+ #
605
+ # Connectors can have a number of adjustments to control the shape
606
+ # routing. Typically, a connector will have 3 to 5 handles for routing
607
+ # the shape. The adjustment is in percent of the distance from the
608
+ # starting shape to the ending shape, alternating between the x and y
609
+ # dimension. Adjustments may be negative, to route the shape away
610
+ # from the endpoint.
611
+ #
612
+ # ==== :stencil
613
+ #
614
+ # Shapes work in stencil mode by default. That is, once a shape is
615
+ # inserted, its connection is separated from its master.
616
+ # The master shape may be modified after an instance is inserted,
617
+ # and only subsequent insertions will show the modifications.
618
+ #
619
+ # This is helpful for Org charts, where an employee shape may be
620
+ # created once, and then the text of the shape is modified for each
621
+ # employee.
622
+ #
623
+ # The insert_shape() method returns a reference to the inserted
624
+ # shape (the child).
625
+ #
626
+ # Stencil mode can be turned off, allowing for shape(s) to be
627
+ # modified after insertion. In this case the insert_shape() method
628
+ # returns a reference to the inserted shape (the master).
629
+ # This is not very useful for inserting multiple shapes,
630
+ # since the x/y coordinates also gets modified.
631
+ #
632
+ def add_shape(properties)
633
+ shape = Shape.new(properties)
634
+ shape[:palette] = @palette
635
+
636
+ @shapes ||= []
637
+ @shapes << shape #Store shape reference.
638
+ shape
639
+ end
640
+
409
641
  #
410
642
  # Create a defined name in Excel. We handle global/workbook level names and
411
643
  # local/worksheet names.
412
644
  #
413
- # This method is used to defined a name that can be used to represent a value,
414
- # a single cell or a range of cells in a workbook.
645
+ # This method is used to defined a name that can be used to represent
646
+ # a value, a single cell or a range of cells in a workbook.
415
647
  #
416
- # For example to set a global/workbook name:
648
+ # For example to set a global/workbook name:
417
649
  #
418
650
  # # Global/workbook names.
419
651
  # workbook.define_name('Exchange_rate', '=0.96')
@@ -424,7 +656,8 @@ def add_format(properties = {})
424
656
  #
425
657
  # # Local/worksheet name.
426
658
  # workbook.define_name('Sheet2!Sales', '=Sheet2!$G$1:$G$10')
427
- # If the sheet name contains spaces or special characters
659
+ #
660
+ # If the sheet name contains spaces or special characters
428
661
  # you must enclose it in single quotes like in Excel:
429
662
  #
430
663
  # workbook.define_name("'New Data'!Sales", '=Sheet2!$G$1:$G$10')
@@ -445,25 +678,22 @@ def define_name(name, formula)
445
678
  name = $2
446
679
  sheet_index = get_sheet_index(sheetname)
447
680
  else
448
- sheet_index =-1 # Use -1 to indicate global names.
681
+ sheet_index = -1 # Use -1 to indicate global names.
449
682
  end
450
683
 
451
684
  # Warn if the sheet index wasn't found.
452
685
  if !sheet_index
453
686
  raise "Unknown sheet name #{sheetname} in defined_name()\n"
454
- return -1
455
687
  end
456
688
 
457
689
  # Warn if the sheet name contains invalid chars as defined by Excel help.
458
690
  if name !~ %r!^[a-zA-Z_\\][a-zA-Z_.]+!
459
691
  raise "Invalid characters in name '#{name}' used in defined_name()\n"
460
- return -1
461
692
  end
462
693
 
463
694
  # Warn if the sheet name looks like a cell name.
464
695
  if name =~ %r(^[a-zA-Z][a-zA-Z]?[a-dA-D]?[0-9]+$)
465
696
  raise "Invalid name '#{name}' looks like a cell name in defined_name()\n"
466
- return -1
467
697
  end
468
698
 
469
699
  @defined_names.push([ name, sheet_index, formula])
@@ -473,7 +703,8 @@ def define_name(name, formula)
473
703
  # The set_properties method can be used to set the document properties
474
704
  # of the Excel file created by WriteXLSX. These properties are visible
475
705
  # when you use the Office Button -> Prepare -> Properties option in Excel
476
- # and are also available to external applications that read or index windows files.
706
+ # and are also available to external applications that read or index windows
707
+ # files.
477
708
  #
478
709
  # The properties should be passed in hash format as follows:
479
710
  #
@@ -495,7 +726,8 @@ def define_name(name, formula)
495
726
  # :comments
496
727
  # :status
497
728
  #
498
- # See also the properties.rb program in the examples directory of the distro.
729
+ # See also the properties.rb program in the examples directory
730
+ # of the distro.
499
731
  #
500
732
  def set_properties(params)
501
733
  # Ignore if no args were passed.
@@ -533,7 +765,8 @@ def set_properties(params)
533
765
  # The set_custom_color() method can be used to override one of the built-in
534
766
  # palette values with a more suitable colour.
535
767
  #
536
- # The value for _index_ should be in the range 8..63, see "COLOURS IN EXCEL".
768
+ # The value for _index_ should be in the range 8..63,
769
+ # see "COLOURS IN EXCEL".
537
770
  #
538
771
  # The default named colours use the following indices:
539
772
  #
@@ -732,46 +965,49 @@ def set_color_palette #:nodoc:
732
965
  # Check for valid worksheet names. We check the length, if it contains any
733
966
  # invalid characters and if the name is unique in the workbook.
734
967
  #
735
- def check_sheetname(name, chart = nil) #:nodoc:
736
- name ||= ''
737
- invalid_char = /[\[\]:*?\/\\]/
738
-
968
+ def check_sheetname(name) #:nodoc:
739
969
  # Increment the Sheet/Chart number used for default sheet names below.
740
- if chart
741
- @chartname_count += 1
742
- else
743
- @sheetname_count += 1
744
- end
970
+ @sheetname_count += 1
745
971
 
746
972
  # Supply default Sheet/Chart name if none has been defined.
747
- if name == ''
748
- if chart
749
- name = "#{@chart_name}#{@chartname_count}"
750
- else
751
- name = "#{@sheet_name}#{@sheetname_count}"
752
- end
973
+ if name.nil? || name == ''
974
+ name = "#{@sheet_name}#{@sheetname_count}"
753
975
  end
976
+ check_valid_sheetname(name)
977
+ name
978
+ end
979
+
980
+ def check_chart_sheetname(name)
981
+ @chartname_count += 1
982
+ if name.nil? || name == ''
983
+ name = "#{@chart_name}#{@chartname_count}"
984
+ end
985
+ check_valid_sheetname(name)
986
+ name
987
+ end
754
988
 
989
+ def check_valid_sheetname(name)
755
990
  # Check that sheet name is <= 31. Excel limit.
756
991
  raise "Sheetname #{name} must be <= #{SHEETNAME_MAX} chars" if name.length > SHEETNAME_MAX
757
992
 
758
993
  # Check that sheetname doesn't contain any invalid characters
994
+ invalid_char = /[\[\]:*?\/\\]/
759
995
  if name =~ invalid_char
760
996
  raise 'Invalid character []:*?/\\ in worksheet name: ' + name
761
997
  end
762
998
 
763
999
  # Check that the worksheet name doesn't already exist since this is a fatal
764
1000
  # error in Excel 97. The check must also exclude case insensitive matches.
765
- @worksheets.each do |worksheet|
766
- name_a = name
767
- name_b = worksheet.name
768
-
769
- if name_a.downcase == name_b.downcase
770
- raise "Worksheet name '#{name}', with case ignored, is already used."
771
- end
1001
+ unless is_sheetname_uniq?(name)
1002
+ raise "Worksheet name '#{name}', with case ignored, is already used."
772
1003
  end
1004
+ end
773
1005
 
774
- name
1006
+ def is_sheetname_uniq?(name)
1007
+ @worksheets.each do |worksheet|
1008
+ return false if name.downcase == worksheet.name.downcase
1009
+ end
1010
+ true
775
1011
  end
776
1012
 
777
1013
  #
@@ -849,11 +1085,14 @@ def write_book_views #:nodoc:
849
1085
 
850
1086
  def write_workbook_view #:nodoc:
851
1087
  attributes = [
852
- 'xWindow', 240,
853
- 'yWindow', 15,
854
- 'windowWidth', 16095,
855
- 'windowHeight', 9660
856
- ]
1088
+ 'xWindow', @x_window,
1089
+ 'yWindow', @y_window,
1090
+ 'windowWidth', @window_width,
1091
+ 'windowHeight', @window_height
1092
+ ]
1093
+ if @tab_ratio != 500
1094
+ attributes << 'tabRatio' << @tab_ratio
1095
+ end
857
1096
  if @firstsheet > 0
858
1097
  attributes << 'firstSheet' << @firstsheet
859
1098
  end
@@ -883,7 +1122,7 @@ def write_sheet(name, sheet_id, hidden = false) #:nodoc:
883
1122
  attributes << 'state' << 'hidden'
884
1123
  end
885
1124
  attributes << 'r:id' << "rId#{sheet_id}"
886
- @writer.empty_tag('sheet', attributes)
1125
+ @writer.empty_tag_encoded('sheet', attributes)
887
1126
  end
888
1127
 
889
1128
  def write_calc_pr #:nodoc:
@@ -956,7 +1195,7 @@ def store_workbook #:nodoc:
956
1195
  @worksheets.first.select if @activesheet == 0
957
1196
 
958
1197
  # Set the active sheet.
959
- @worksheets.each { |sheet| sheet.activate if sheet.index == @activesheet }
1198
+ @worksheets[@activesheet].activate
960
1199
 
961
1200
  prepare_comments # Prepare the worksheet cell comments.
962
1201
  prepare_defined_names # Set the defined names for the worksheets such as Print Titles.
@@ -1018,12 +1257,8 @@ def prepare_formats #:nodoc:
1018
1257
  #
1019
1258
  def prepare_fonts #:nodoc:
1020
1259
  fonts = {}
1021
- @xf_formats.each do |format|
1022
- key = format.get_font_key
1023
- format.has_font(!fonts[key])
1024
- format.font_index = fonts[key] || fonts.size
1025
- fonts[key] ||= fonts.size
1026
- end
1260
+
1261
+ @xf_formats.each { |format| format.set_font_info(fonts) }
1027
1262
 
1028
1263
  @font_count = fonts.size
1029
1264
 
@@ -1031,7 +1266,7 @@ def prepare_fonts #:nodoc:
1031
1266
  @dxf_formats.each do |format|
1032
1267
  # The only font properties that can change for a DXF format are: color,
1033
1268
  # bold, italic, underline and strikethrough.
1034
- if format.color || format.bold? || format.italic? || format.underline? || format.strikeout?
1269
+ if format.color? || format.bold? || format.italic? || format.underline? || format.strikeout?
1035
1270
  format.has_dxf_font(true)
1036
1271
  end
1037
1272
  end
@@ -1071,7 +1306,7 @@ def prepare_num_formats #:nodoc:
1071
1306
  index += 1
1072
1307
 
1073
1308
  # Only increase font count for XF formats (not for DXF formats).
1074
- num_format_count += 1 unless format.xf_index == 0
1309
+ num_format_count += 1 if ptrue?(format.xf_index)
1075
1310
  end
1076
1311
  end
1077
1312
 
@@ -1084,12 +1319,8 @@ def prepare_num_formats #:nodoc:
1084
1319
  #
1085
1320
  def prepare_borders #:nodoc:
1086
1321
  borders = {}
1087
- @xf_formats.each do |format|
1088
- key = format.get_border_key
1089
- format.has_border(!borders[key])
1090
- format.border_index = borders[key] || borders.size
1091
- borders[key] ||= borders.size
1092
- end
1322
+
1323
+ @xf_formats.each { |format| format.set_border_info(borders) }
1093
1324
 
1094
1325
  @border_count = borders.size
1095
1326
 
@@ -1115,6 +1346,15 @@ def prepare_fills #:nodoc:
1115
1346
  fills['0:0:0'] = 0
1116
1347
  fills['17:0:0'] = 1
1117
1348
 
1349
+ # Store the DXF colors separately since them may be reversed below.
1350
+ @dxf_formats.each do |format|
1351
+ if format.pattern != 0 || format.bg_color != 0 || format.fg_color != 0
1352
+ format.has_dxf_fill(true)
1353
+ format.dxf_bg_color = format.bg_color
1354
+ format.dxf_fg_color = format.fg_color
1355
+ end
1356
+ end
1357
+
1118
1358
  @xf_formats.each do |format|
1119
1359
  # The following logical statements jointly take care of special cases
1120
1360
  # in relation to cell colours and patterns:
@@ -1124,13 +1364,13 @@ def prepare_fills #:nodoc:
1124
1364
  # a pattern they probably wanted a solid fill, so we fill in the
1125
1365
  # defaults.
1126
1366
  #
1127
- if format.pattern <= 1 && format.bg_color != 0 && format.fg_color == 0
1367
+ if format.pattern == 1 && ne_0?(format.bg_color) && ne_0?(format.fg_color)
1368
+ format.fg_color, format.bg_color = format.bg_color, format.fg_color
1369
+ elsif format.pattern <= 1 && ne_0?(format.bg_color) && eq_0?(format.fg_color)
1128
1370
  format.fg_color = format.bg_color
1129
1371
  format.bg_color = 0
1130
1372
  format.pattern = 1
1131
- end
1132
-
1133
- if format.pattern <= 1 && format.bg_color == 0 && format.fg_color != 0
1373
+ elsif format.pattern <= 1 && eq_0?(format.bg_color) && ne_0?(format.fg_color)
1134
1374
  format.bg_color = 0
1135
1375
  format.pattern = 1
1136
1376
  end
@@ -1151,11 +1391,14 @@ def prepare_fills #:nodoc:
1151
1391
  end
1152
1392
 
1153
1393
  @fill_count = index
1394
+ end
1154
1395
 
1155
- # For the DXF formats we only need to check if the properties have changed.
1156
- @dxf_formats.each do |format|
1157
- format.has_dxf_fill(true) if format.pattern || format.bg_color || format.fg_color
1158
- end
1396
+ def eq_0?(val)
1397
+ ptrue?(val) ? false : true
1398
+ end
1399
+
1400
+ def ne_0?(val)
1401
+ !eq_0?(val)
1159
1402
  end
1160
1403
 
1161
1404
  #
@@ -1216,6 +1459,7 @@ def prepare_comments #:nodoc:
1216
1459
  next unless sheet.has_comments?
1217
1460
 
1218
1461
  comment_id += 1
1462
+ sheet.set_external_vml_links(comment_id)
1219
1463
  sheet.set_external_comment_links(comment_id)
1220
1464
  sheet.set_vml_data_id(vml_data_id)
1221
1465
  sheet.vml_shape_id = vml_shape_id
@@ -1259,15 +1503,10 @@ def add_chart_data #:nodoc:
1259
1503
  chart.formula_ids.each do |range, id|
1260
1504
  # Skip if the series has user defined data.
1261
1505
  if chart.formula_data[id]
1262
- if !seen_ranges.has_key?(range) || seen_ranges[range]
1263
- data = chart.formula_data[id]
1264
- seen_ranges[range] = data
1265
- end
1506
+ seen_ranges[range] = chart.formula_data[id] unless seen_ranges[range]
1266
1507
  next
1267
- end
1268
-
1269
1508
  # Check to see if the data is already cached locally.
1270
- if seen_ranges.has_key?(range)
1509
+ elsif seen_ranges[range]
1271
1510
  chart.formula_data[id] = seen_ranges[range]
1272
1511
  next
1273
1512
  end
@@ -1278,34 +1517,41 @@ def add_chart_data #:nodoc:
1278
1517
  # Skip if we couldn't parse the formula.
1279
1518
  next unless sheetname
1280
1519
 
1281
- # Skip if the name is unknown. Probably should throw exception.
1282
- next unless worksheets[sheetname]
1520
+ # Raise if the name is unknown since it indicates a user error in
1521
+ # a chart series formula.
1522
+ unless worksheets[sheetname]
1523
+ raise "Unknown worksheet reference '#{sheetname} in range '#{range}' passed to add_series()\n"
1524
+ end
1283
1525
 
1284
- # Find the worksheet object based on the sheet name.
1285
- worksheet = worksheets[sheetname]
1526
+ # Add the data to the chart.
1527
+ # And store range data locally to avoid lookup if seen agein.
1528
+ chart.formula_data[id] =
1529
+ seen_ranges[range] = chart_data(worksheets[sheetname], cells)
1530
+ end
1531
+ end
1532
+ end
1286
1533
 
1287
- # Get the data from the worksheet table.
1288
- data = worksheet.get_range_data(*cells)
1534
+ def chart_data(worksheet, cells)
1535
+ # Get the data from the worksheet table.
1536
+ data = worksheet.get_range_data(*cells)
1289
1537
 
1290
- # Convert shared string indexes to strings.
1291
- data.collect! do |token|
1292
- if token.kind_of?(Hash)
1293
- token = @shared_strings.string(token[:sst_id])
1538
+ # Convert shared string indexes to strings.
1539
+ data.collect do |token|
1540
+ if token.kind_of?(Hash)
1541
+ string = @shared_strings.string(token[:sst_id])
1294
1542
 
1295
- # Ignore rich strings for now. Deparse later if necessary.
1296
- token = '' if token =~ %r!^<r>! && token =~ %r!</r>$!
1297
- end
1298
- token
1543
+ # Ignore rich strings for now. Deparse later if necessary.
1544
+ if string =~ %r!^<r>! && string =~ %r!</r>$!
1545
+ ''
1546
+ else
1547
+ string
1299
1548
  end
1300
-
1301
- # Add the data to the chart.
1302
- chart.formula_data[id] = data
1303
-
1304
- # Store range data locally to avoid lookup if seen again.
1305
- seen_ranges[range] = data
1549
+ else
1550
+ token
1306
1551
  end
1307
1552
  end
1308
1553
  end
1554
+ private :chart_data
1309
1555
 
1310
1556
  #
1311
1557
  # Sort internal and user defined names in the same order as used by Excel.
@@ -1367,9 +1613,9 @@ def extract_named_ranges(defined_names) #:nodoc:
1367
1613
  # Match Print_Area and Print_Titles xlnm types.
1368
1614
  if name =~ /^_xlnm\.(.*)$/
1369
1615
  xlnm_type = $1
1370
- name = sheet_name + '!' + xlnm_type
1616
+ name = "#{sheet_name}!#{xlnm_type}"
1371
1617
  elsif index != -1
1372
- name = sheet_name + '!' + name
1618
+ name = "#{sheet_name}!#{name}"
1373
1619
  end
1374
1620
 
1375
1621
  named_ranges << name
@@ -1389,7 +1635,10 @@ def prepare_drawings #:nodoc:
1389
1635
  @worksheets.each do |sheet|
1390
1636
  chart_count = sheet.charts.size
1391
1637
  image_count = sheet.images.size
1392
- next if chart_count + image_count == 0
1638
+ shape_count = sheet.shapes.size
1639
+ next if chart_count + image_count + shape_count == 0
1640
+
1641
+ sheet.sort_charts
1393
1642
 
1394
1643
  drawing_id += 1
1395
1644
 
@@ -1408,6 +1657,10 @@ def prepare_drawings #:nodoc:
1408
1657
  sheet.prepare_image(index, image_ref_id, drawing_id, width, height, name, type)
1409
1658
  end
1410
1659
 
1660
+ (0..shape_count - 1).each do |index|
1661
+ sheet.prepare_shape(index, drawing_id)
1662
+ end
1663
+
1411
1664
  drawing = sheet.drawing
1412
1665
  @drawings << drawing
1413
1666
  end
@@ -1431,5 +1684,110 @@ def get_sheet_index(sheetname) #:nodoc:
1431
1684
 
1432
1685
  sheet_index
1433
1686
  end
1687
+
1688
+ #
1689
+ # Extract information from the image file such as dimension, type, filename,
1690
+ # and extension. Also keep track of previously seen images to optimise out
1691
+ # any duplicates.
1692
+ #
1693
+ def get_image_properties(filename)
1694
+ previous_images = []
1695
+ image_id = 1;
1696
+ if @images_seen[filename]
1697
+ # We've processed this file already.
1698
+ index = images_seen[filename] - 1
1699
+
1700
+ # Increase image reference count.
1701
+ image_data[index][0] += 1
1702
+ else
1703
+ # Open the image file and import the data.
1704
+ data = File.binread(filename)
1705
+ if data.unpack('x A3')[0] == 'PNG'
1706
+ # Test for PNGs.
1707
+ type, width, height = process_png(data)
1708
+ image_types[:png] = 1
1709
+ elsif data.unpack('n')[0] == 0xFFD8 &&
1710
+ (data.unpack('x6 A4')[0] == 'JFIF' || data.unpack('x6 A4')[0] == 'Exif')
1711
+ # Test for JFIF and Exif JPEGs.
1712
+ type, width, height = process_jpg(data, filename)
1713
+ @image_types[:jpeg] = 1
1714
+ elsif data.unpack('A2')[0] == 'BM'
1715
+ # Test for BMPs.
1716
+ type, width, height = process_bmp(data, filename)
1717
+ @image_types[:bmp] = 1
1718
+ else
1719
+ # TODO. Add Image::Size to support other types.
1720
+ raise "Unsupported image format for file: #{filename}\n"
1721
+ end
1722
+
1723
+ @images << [ filename, type]
1724
+
1725
+ # Also store new data for use in duplicate images.
1726
+ previous_images << [image_id, type, width, height]
1727
+ @images_seen[filename] = image_id
1728
+ image_id += 1
1729
+ end
1730
+
1731
+ [image_id, type, width, height, File.basename(filename)]
1732
+ end
1733
+
1734
+ #
1735
+ # Extract width and height information from a PNG file.
1736
+ #
1737
+ def process_png(data)
1738
+ type = 'png'
1739
+ width = data[16, 4].unpack("N")[0]
1740
+ height = data[20, 4].unpack("N")[0]
1741
+
1742
+ [type, width, height]
1743
+ end
1744
+
1745
+ def process_jpg(data, filename)
1746
+ type = 'jpeg'
1747
+ offset = 2
1748
+ data_length = data.bytesize
1749
+
1750
+ # Search through the image data to find the 0xFFC0 marker. The height and
1751
+ # width are contained in the data for that sub element.
1752
+ while offset < data_length
1753
+ marker = data[offset, 2].unpack("n")[0]
1754
+ length = data[offset+2, 2].unpack("n")[0]
1755
+
1756
+ if marker == 0xFFC0 || marker == 0xFFC2
1757
+ height = data[offset+5, 2].unpack("n")[0]
1758
+ width = data[offset+7, 2].unpack("n")[0]
1759
+ break
1760
+ end
1761
+
1762
+ offset += length + 2
1763
+ break if marker == 0xFFDA
1764
+ end
1765
+
1766
+ raise "#{filename}: no size data found in jpeg image.\n" unless height
1767
+ [type, width, height]
1768
+ end
1769
+
1770
+ # Extract width and height information from a BMP file.
1771
+ def process_bmp(data, filename) #:nodoc:
1772
+ type = 'bmp'
1773
+
1774
+ # Check that the file is big enough to be a bitmap.
1775
+ raise "#{filename} doesn't contain enough data." if data.bytesize <= 0x36
1776
+
1777
+ # Read the bitmap width and height. Verify the sizes.
1778
+ width, height = data.unpack("x18 V2")
1779
+ raise "#{filename}: largest image width #{width} supported is 65k." if width > 0xFFFF
1780
+ raise "#{filename}: largest image height supported is 65k." if height > 0xFFFF
1781
+
1782
+ # Read the bitmap planes and bpp data. Verify them.
1783
+ planes, bitcount = data.unpack("x26 v2")
1784
+ raise "#{filename} isn't a 24bit true color bitmap." unless bitcount == 24
1785
+ raise "#{filename}: only 1 plane supported in bitmap image." unless planes == 1
1786
+
1787
+ # Read the bitmap compression. Verify compression.
1788
+ compression = data.unpack("x30 V")[0]
1789
+ raise "#{filename}: compression not supported in bitmap image." unless compression == 0
1790
+ [type, width, height]
1791
+ end
1434
1792
  end
1435
1793
  end