/vendor/gems/spreadsheet-0.6.4.1/lib/spreadsheet/excel/writer/format.rb

https://github.com/jcn/awesomefoundation · Ruby · 253 lines · 165 code · 1 blank · 87 comment · 20 complexity · fde613f1db946eb02eef475319fc25b8 MD5 · raw file

  1. require 'delegate'
  2. require 'spreadsheet/format'
  3. require 'spreadsheet/excel/internals'
  4. module Spreadsheet
  5. module Excel
  6. module Writer
  7. ##
  8. # This class encapsulates everything that is needed to write an XF record.
  9. class Format < DelegateClass Spreadsheet::Format
  10. include Spreadsheet::Excel::Internals
  11. def Format.boolean *args
  12. args.each do |key|
  13. define_method key do
  14. @format.send("#{key}?") ? 1 : 0
  15. end
  16. end
  17. end
  18. def Format.color key, default
  19. define_method key do
  20. color_code(@format.send(key) || default)
  21. end
  22. end
  23. boolean :hidden, :locked, :merge_range, :shrink, :text_justlast, :text_wrap,
  24. :cross_down, :cross_up, :left, :right, :top, :bottom
  25. color :left_color, :border
  26. color :right_color, :border
  27. color :top_color, :border
  28. color :bottom_color, :border
  29. color :diagonal_color, :border
  30. color :pattern_fg_color, :pattern_bg
  31. color :pattern_bg_color, :pattern_bg
  32. attr_accessor :xf_index
  33. attr_reader :format
  34. def initialize writer, workbook, format=workbook.default_format, opts={}
  35. @opts = { :type => :format }.merge opts
  36. @format = format
  37. @writer = writer
  38. @workbook = workbook
  39. super format
  40. end
  41. def color_code color
  42. SEDOC_ROLOC[color]
  43. end
  44. def font_index
  45. @writer.font_index @workbook, font.key
  46. end
  47. def horizontal_align
  48. XF_H_ALIGN.fetch @format.horizontal_align, 0
  49. end
  50. def num_format
  51. @writer.number_format_index @workbook, @format.number_format
  52. end
  53. def text_direction
  54. XF_TEXT_DIRECTION.fetch @format.text_direction, 0
  55. end
  56. def vertical_align
  57. XF_V_ALIGN.fetch @format.vertical_align, 2
  58. end
  59. def write_op writer, op, *args
  60. data = args.join
  61. writer.write [op,data.size].pack("v2")
  62. writer.write data
  63. end
  64. def write_xf writer, type=@opts[:type]
  65. xf_type = xf_type_prot type
  66. data = [
  67. font_index, # Index to FONT record ( 6.43)
  68. num_format, # Index to FORMAT record ( 6.45)
  69. xf_type, # Bit Mask Contents
  70. # 2-0 0x0007 XF_TYPE_PROT XF type, cell protection
  71. # Bit Mask Contents
  72. # 0 0x01 1 = Cell is locked
  73. # 1 0x02 1 = Formula is hidden
  74. # 2 0x04 0 = Cell XF; 1 = Style XF
  75. # 15-4 0xfff0 Index to parent style XF
  76. # (always 0xfff in style XFs)
  77. xf_align, # Bit Mask Contents
  78. # 2-0 0x07 XF_HOR_ALIGN Horizontal alignment
  79. # Value Horizontal alignment
  80. # 0x00 General
  81. # 0x01 Left
  82. # 0x02 Centred
  83. # 0x03 Right
  84. # 0x04 Filled
  85. # 0x05 Justified (BIFF4-BIFF8X)
  86. # 0x06 Centred across selection
  87. # (BIFF4-BIFF8X)
  88. # 0x07 Distributed (BIFF8X)
  89. # 3 0x08 1 = Text is wrapped at right border
  90. # 6-4 0x70 XF_VERT_ALIGN Vertical alignment
  91. # Value Vertical alignment
  92. # 0x00 Top
  93. # 0x01 Centred
  94. # 0x02 Bottom
  95. # 0x03 Justified (BIFF5-BIFF8X)
  96. # 0x04 Distributed (BIFF8X)
  97. xf_rotation, # XF_ROTATION: Text rotation angle
  98. # Value Text rotation
  99. # 0 Not rotated
  100. # 1-90 1 to 90 degrees counterclockwise
  101. # 91-180 1 to 90 degrees clockwise
  102. # 255 Letters are stacked top-to-bottom,
  103. # but not rotated
  104. xf_indent, # Bit Mask Contents
  105. # 3-0 0x0f Indent level
  106. # 4 0x10 1 = Shrink content to fit into cell
  107. # 5 0x40 1 = Merge Range (djberger)
  108. # 7-6 0xc0 Text direction (BIFF8X only)
  109. # 0 = According to context
  110. # 1 = Left-to-right
  111. # 2 = Right-to-left
  112. xf_used_attr, # Bit Mask Contents
  113. # 7-2 0xfc XF_USED_ATTRIB Used attributes
  114. # Each bit describes the validity of a
  115. # specific group of attributes. In cell XFs
  116. # a cleared bit means the attributes of the
  117. # parent style XF are used (but only if the
  118. # attributes are valid there), a set bit
  119. # means the attributes of this XF are used.
  120. # In style XFs a cleared bit means the
  121. # attribute setting is valid, a set bit
  122. # means the attribute should be ignored.
  123. # Bit Mask Contents
  124. # 0 0x01 Flag for number format
  125. # 1 0x02 Flag for font
  126. # 2 0x04 Flag for horizontal and
  127. # vertical alignment, text wrap,
  128. # indentation, orientation,
  129. # rotation, and text direction
  130. # 3 0x08 Flag for border lines
  131. # 4 0x10 Flag for background area style
  132. # 5 0x20 Flag for cell protection (cell
  133. # locked and formula hidden)
  134. xf_borders, # Cell border lines and background area:
  135. # Bit Mask Contents
  136. # 3- 0 0x0000000f Left line style ( 3.10)
  137. # 7- 4 0x000000f0 Right line style ( 3.10)
  138. # 11- 8 0x00000f00 Top line style ( 3.10)
  139. # 15-12 0x0000f000 Bottom line style ( 3.10)
  140. # 22-16 0x007f0000 Colour index ( 6.70)
  141. # for left line colour
  142. # 29-23 0x3f800000 Colour index ( 6.70)
  143. # for right line colour
  144. # 30 0x40000000 1 = Diagonal line
  145. # from top left to right bottom
  146. # 31 0x80000000 1 = Diagonal line
  147. # from bottom left to right top
  148. xf_brdcolors, # Bit Mask Contents
  149. # 6- 0 0x0000007f Colour index ( 6.70)
  150. # for top line colour
  151. # 13- 7 0x00003f80 Colour index ( 6.70)
  152. # for bottom line colour
  153. # 20-14 0x001fc000 Colour index ( 6.70)
  154. # for diagonal line colour
  155. # 24-21 0x01e00000 Diagonal line style ( 3.10)
  156. # 31-26 0xfc000000 Fill pattern ( 3.11)
  157. xf_pattern # Bit Mask Contents
  158. # 6-0 0x007f Colour index ( 6.70)
  159. # for pattern colour
  160. # 13-7 0x3f80 Colour index ( 6.70)
  161. # for pattern background
  162. ]
  163. write_op writer, 0x00e0, data.pack(binfmt(:xf))
  164. end
  165. def xf_align
  166. align = horizontal_align
  167. align |= text_wrap << 3
  168. align |= vertical_align << 4
  169. align |= text_justlast << 7
  170. align
  171. end
  172. def xf_borders
  173. border = left
  174. border |= right << 4
  175. border |= top << 8
  176. border |= bottom << 12
  177. border |= left_color << 16
  178. border |= right_color << 23
  179. border |= cross_down << 30
  180. border |= cross_up << 31
  181. border
  182. end
  183. def xf_brdcolors
  184. border = top_color
  185. border |= bottom_color << 7
  186. border |= diagonal_color << 14
  187. border |= pattern << 26
  188. border
  189. end
  190. def xf_indent
  191. indent = indent_level & 0x0f
  192. indent |= shrink << 4
  193. indent |= merge_range << 5
  194. indent |= text_direction << 6
  195. indent
  196. end
  197. def xf_pattern
  198. ptrn = pattern_fg_color
  199. ptrn |= pattern_bg_color << 7
  200. ptrn
  201. end
  202. def xf_rotation
  203. rot = @format.rotation
  204. if @format.rotation_stacked?
  205. rot = 255
  206. elsif rot >= -90 or rotation <= 90
  207. rot = -rot + 90 if rot < 0
  208. else
  209. warn "rotation outside -90..90; rotation set to 0"
  210. rot = 0
  211. end
  212. rot
  213. end
  214. def xf_type_prot type
  215. type = type.to_s.downcase == 'style' ? 0xfff5 : 0x0000
  216. type |= locked
  217. type |= hidden << 1
  218. type
  219. end
  220. def xf_used_attr
  221. atr_num = num_format & 1
  222. atr_fnt = font_index & 1
  223. atr_fnt = 1 unless @format.font.color == :text
  224. atr_alc = 0
  225. if horizontal_align != 0 \
  226. || vertical_align != 2 \
  227. || indent_level > 0 \
  228. || shrink? || merge_range? || text_wrap?
  229. then
  230. atr_alc = 1
  231. end
  232. atr_bdr = [top, bottom, left, right, cross_up, cross_down].max
  233. atr_pat = 0
  234. if @format.pattern_fg_color != :border \
  235. || @format.pattern_bg_color != :pattern_bg \
  236. || pattern != 0x00
  237. then
  238. atr_pat = 1
  239. end
  240. atr_prot = hidden? || locked? ? 1 : 0
  241. attrs = atr_num
  242. attrs |= atr_fnt << 1
  243. attrs |= atr_alc << 2
  244. attrs |= atr_bdr << 3
  245. attrs |= atr_pat << 4
  246. attrs |= atr_prot << 5
  247. attrs << 2
  248. end
  249. end
  250. end
  251. end
  252. end