cell.go 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. package xlsx
  2. import (
  3. "fmt"
  4. "math"
  5. "strconv"
  6. )
  7. // CellType is an int type for storing metadata about the data type in the cell.
  8. type CellType int
  9. // Known types for cell values.
  10. const (
  11. CellTypeString CellType = iota
  12. CellTypeFormula
  13. CellTypeNumeric
  14. CellTypeBool
  15. CellTypeInline
  16. CellTypeError
  17. )
  18. // Cell is a high level structure intended to provide user access to
  19. // the contents of Cell within an xlsx.Row.
  20. type Cell struct {
  21. Row *Row
  22. Value string
  23. formula string
  24. style *Style
  25. numFmt string
  26. date1904 bool
  27. Hidden bool
  28. HMerge int
  29. VMerge int
  30. cellType CellType
  31. }
  32. // CellInterface defines the public API of the Cell.
  33. type CellInterface interface {
  34. String() string
  35. FormattedValue() string
  36. }
  37. // NewCell creates a cell and adds it to a row.
  38. func NewCell(r *Row) *Cell {
  39. return &Cell{style: NewStyle(), Row: r}
  40. }
  41. // Merge with other cells, horizontally and/or vertically.
  42. func (c *Cell) Merge(hcells, vcells int) {
  43. c.HMerge = hcells
  44. c.VMerge = vcells
  45. }
  46. // Type returns the CellType of a cell. See CellType constants for more details.
  47. func (c *Cell) Type() CellType {
  48. return c.cellType
  49. }
  50. // SetString sets the value of a cell to a string.
  51. func (c *Cell) SetString(s string) {
  52. c.Value = s
  53. c.formula = ""
  54. c.cellType = CellTypeString
  55. }
  56. // String returns the value of a Cell as a string.
  57. func (c *Cell) String() string {
  58. return c.FormattedValue()
  59. }
  60. // SetFloat sets the value of a cell to a float.
  61. func (c *Cell) SetFloat(n float64) {
  62. c.SetFloatWithFormat(n, "0.00e+00")
  63. }
  64. /*
  65. The following are samples of format samples.
  66. * "0.00e+00"
  67. * "0", "#,##0"
  68. * "0.00", "#,##0.00", "@"
  69. * "#,##0 ;(#,##0)", "#,##0 ;[red](#,##0)"
  70. * "#,##0.00;(#,##0.00)", "#,##0.00;[red](#,##0.00)"
  71. * "0%", "0.00%"
  72. * "0.00e+00", "##0.0e+0"
  73. */
  74. // SetFloatWithFormat sets the value of a cell to a float and applies
  75. // formatting to the cell.
  76. func (c *Cell) SetFloatWithFormat(n float64, format string) {
  77. // tmp value. final value is formatted by FormattedValue() method
  78. c.Value = fmt.Sprintf("%e", n)
  79. c.numFmt = format
  80. c.formula = ""
  81. c.cellType = CellTypeNumeric
  82. }
  83. // Float returns the value of cell as a number.
  84. func (c *Cell) Float() (float64, error) {
  85. f, err := strconv.ParseFloat(c.Value, 64)
  86. if err != nil {
  87. return math.NaN(), err
  88. }
  89. return f, nil
  90. }
  91. // SetInt64 sets a cell's value to a 64-bit integer.
  92. func (c *Cell) SetInt64(n int64) {
  93. c.Value = fmt.Sprintf("%d", n)
  94. c.numFmt = "0"
  95. c.formula = ""
  96. c.cellType = CellTypeNumeric
  97. }
  98. // Int64 returns the value of cell as 64-bit integer.
  99. func (c *Cell) Int64() (int64, error) {
  100. f, err := strconv.ParseInt(c.Value, 10, 64)
  101. if err != nil {
  102. return -1, err
  103. }
  104. return f, nil
  105. }
  106. // SetInt sets a cell's value to an integer.
  107. func (c *Cell) SetInt(n int) {
  108. c.Value = fmt.Sprintf("%d", n)
  109. c.numFmt = "0"
  110. c.formula = ""
  111. c.cellType = CellTypeNumeric
  112. }
  113. // Int returns the value of cell as integer.
  114. // Has max 53 bits of precision
  115. // See: float64(int64(math.MaxInt))
  116. func (c *Cell) Int() (int, error) {
  117. f, err := strconv.ParseFloat(c.Value, 64)
  118. if err != nil {
  119. return -1, err
  120. }
  121. return int(f), nil
  122. }
  123. // SetBool sets a cell's value to a boolean.
  124. func (c *Cell) SetBool(b bool) {
  125. if b {
  126. c.Value = "1"
  127. } else {
  128. c.Value = "0"
  129. }
  130. c.cellType = CellTypeBool
  131. }
  132. // Bool returns a boolean from a cell's value.
  133. // TODO: Determine if the current return value is
  134. // appropriate for types other than CellTypeBool.
  135. func (c *Cell) Bool() bool {
  136. // If bool, just return the value.
  137. if c.cellType == CellTypeBool {
  138. return c.Value == "1"
  139. }
  140. // If numeric, base it on a non-zero.
  141. if c.cellType == CellTypeNumeric {
  142. return c.Value != "0"
  143. }
  144. // Return whether there's an empty string.
  145. return c.Value != ""
  146. }
  147. // SetFormula sets the format string for a cell.
  148. func (c *Cell) SetFormula(formula string) {
  149. c.formula = formula
  150. c.cellType = CellTypeFormula
  151. }
  152. // Formula returns the formula string for the cell.
  153. func (c *Cell) Formula() string {
  154. return c.formula
  155. }
  156. // GetStyle returns the Style associated with a Cell
  157. func (c *Cell) GetStyle() *Style {
  158. return c.style
  159. }
  160. // SetStyle sets the style of a cell.
  161. func (c *Cell) SetStyle(style *Style) {
  162. c.style = style
  163. }
  164. // GetNumberFormat returns the number format string for a cell.
  165. func (c *Cell) GetNumberFormat() string {
  166. return c.numFmt
  167. }
  168. func (c *Cell) formatToTime(format string) string {
  169. f, err := strconv.ParseFloat(c.Value, 64)
  170. if err != nil {
  171. return err.Error()
  172. }
  173. return TimeFromExcelTime(f, c.date1904).Format(format)
  174. }
  175. func (c *Cell) formatToFloat(format string) string {
  176. f, err := strconv.ParseFloat(c.Value, 64)
  177. if err != nil {
  178. return err.Error()
  179. }
  180. return fmt.Sprintf(format, f)
  181. }
  182. func (c *Cell) formatToInt(format string) string {
  183. f, err := strconv.ParseFloat(c.Value, 64)
  184. if err != nil {
  185. return err.Error()
  186. }
  187. return fmt.Sprintf(format, int(f))
  188. }
  189. // FormattedValue returns the formatted version of the value.
  190. // If it's a string type, c.Value will just be returned. Otherwise,
  191. // it will attempt to apply Excel formatting to the value.
  192. func (c *Cell) FormattedValue() string {
  193. var numberFormat = c.GetNumberFormat()
  194. switch numberFormat {
  195. case "general", "@":
  196. return c.Value
  197. case "0", "#,##0":
  198. return c.formatToInt("%d")
  199. case "0.00", "#,##0.00":
  200. return c.formatToFloat("%.2f")
  201. case "#,##0 ;(#,##0)", "#,##0 ;[red](#,##0)":
  202. f, err := strconv.ParseFloat(c.Value, 64)
  203. if err != nil {
  204. return err.Error()
  205. }
  206. if f < 0 {
  207. i := int(math.Abs(f))
  208. return fmt.Sprintf("(%d)", i)
  209. }
  210. i := int(f)
  211. return fmt.Sprintf("%d", i)
  212. case "#,##0.00;(#,##0.00)", "#,##0.00;[red](#,##0.00)":
  213. f, err := strconv.ParseFloat(c.Value, 64)
  214. if err != nil {
  215. return err.Error()
  216. }
  217. if f < 0 {
  218. return fmt.Sprintf("(%.2f)", f)
  219. }
  220. return fmt.Sprintf("%.2f", f)
  221. case "0%":
  222. f, err := strconv.ParseFloat(c.Value, 64)
  223. if err != nil {
  224. return err.Error()
  225. }
  226. f = f * 100
  227. return fmt.Sprintf("%d%%", int(f))
  228. case "0.00%":
  229. f, err := strconv.ParseFloat(c.Value, 64)
  230. if err != nil {
  231. return err.Error()
  232. }
  233. f = f * 100
  234. return fmt.Sprintf("%.2f%%", f)
  235. case "0.00e+00", "##0.0e+0":
  236. return c.formatToFloat("%e")
  237. case "mm-dd-yy":
  238. return c.formatToTime("01-02-06")
  239. case "d-mmm-yy":
  240. return c.formatToTime("2-Jan-06")
  241. case "d-mmm":
  242. return c.formatToTime("2-Jan")
  243. case "mmm-yy":
  244. return c.formatToTime("Jan-06")
  245. case "h:mm am/pm":
  246. return c.formatToTime("3:04 pm")
  247. case "h:mm:ss am/pm":
  248. return c.formatToTime("3:04:05 pm")
  249. case "h:mm":
  250. return c.formatToTime("15:04")
  251. case "h:mm:ss":
  252. return c.formatToTime("15:04:05")
  253. case "m/d/yy h:mm":
  254. return c.formatToTime("1/2/06 15:04")
  255. case "mm:ss":
  256. return c.formatToTime("04:05")
  257. case "[h]:mm:ss":
  258. f, err := strconv.ParseFloat(c.Value, 64)
  259. if err != nil {
  260. return err.Error()
  261. }
  262. t := TimeFromExcelTime(f, c.date1904)
  263. if t.Hour() > 0 {
  264. return t.Format("15:04:05")
  265. }
  266. return t.Format("04:05")
  267. case "mmss.0":
  268. f, err := strconv.ParseFloat(c.Value, 64)
  269. if err != nil {
  270. return err.Error()
  271. }
  272. t := TimeFromExcelTime(f, c.date1904)
  273. return fmt.Sprintf("%0d%0d.%d", t.Minute(), t.Second(), t.Nanosecond()/1000)
  274. case "yyyy\\-mm\\-dd", "yyyy\\-mm\\-dd;@":
  275. return c.formatToTime("2006\\-01\\-02")
  276. case "dd/mm/yy":
  277. return c.formatToTime("02/01/06")
  278. case "hh:mm:ss":
  279. return c.formatToTime("15:04:05")
  280. case "dd/mm/yy\\ hh:mm":
  281. return c.formatToTime("02/01/06\\ 15:04")
  282. case "dd/mm/yyyy hh:mm:ss":
  283. return c.formatToTime("02/01/2006 15:04:05")
  284. case "yyyy/mm/dd":
  285. return c.formatToTime("2006/01/02")
  286. case "yy-mm-dd":
  287. return c.formatToTime("06-01-02")
  288. case "d-mmm-yyyy":
  289. return c.formatToTime("2-Jan-2006")
  290. case "m/d/yy":
  291. return c.formatToTime("1/2/06")
  292. case "m/d/yyyy":
  293. return c.formatToTime("1/2/2006")
  294. case "dd-mmm-yyyy":
  295. return c.formatToTime("02-Jan-2006")
  296. case "dd/mm/yyyy":
  297. return c.formatToTime("02/01/2006")
  298. case "mm/dd/yy hh:mm am/pm":
  299. return c.formatToTime("01/02/06 03:04 pm")
  300. case "mm/dd/yyyy hh:mm:ss":
  301. return c.formatToTime("01/02/2006 15:04:05")
  302. case "yyyy-mm-dd hh:mm:ss":
  303. return c.formatToTime("2006-01-02 15:04:05")
  304. }
  305. return c.Value
  306. }