cell_formula.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. package xvdoc
  2. import (
  3. "fmt"
  4. "strings"
  5. )
  6. func constructorFormula(m JSONMap) (res Cell, err error) {
  7. if method := m.StringVal("method", ""); len(method) > 0 {
  8. var args []CellArg
  9. if ai := m.Array("args"); len(ai) > 0 {
  10. var arg CellArg
  11. args = make([]CellArg, len(ai))
  12. for i, v := range ai {
  13. if arg, err = argFromIface(v); err == nil {
  14. args[i] = arg
  15. } else {
  16. return
  17. }
  18. }
  19. }
  20. res = &CellFormula{
  21. method: method,
  22. args: args,
  23. style: m.StringVal("style", ""),
  24. styles: m.StringArray("styles"),
  25. }
  26. } else {
  27. err = fmt.Errorf("Formula constructor error: empty method")
  28. }
  29. return
  30. }
  31. // CellFormula is cell of formula for excel or other types with formula support
  32. type CellFormula struct {
  33. method string
  34. args []CellArg
  35. styles []string
  36. style string
  37. }
  38. // Val is method of getter formula string (Cell interface)
  39. func (s *CellFormula) Val() interface{} {
  40. return s.method
  41. }
  42. // Type method is value type getter (formula)
  43. func (s *CellFormula) Type() string {
  44. return "formula"
  45. }
  46. func (s *CellFormula) String() string {
  47. return fmt.Sprintf("{ formula :: %v, args: [ %v ]}", s.method, s.args)
  48. }
  49. // ReplaceArgs is replace variable templates ($1, $2, etc) to valus from incoming array
  50. func (s *CellFormula) ReplaceArgs(args []string) (res string) {
  51. res = s.method
  52. for i, arg := range args {
  53. res = strings.ReplaceAll(res, fmt.Sprintf("$%v", i+1), arg)
  54. }
  55. return res
  56. }
  57. // Style is getter of cell style
  58. func (s *CellFormula) Styles() (res []string) {
  59. if len(s.styles) > 0 {
  60. res = s.styles
  61. } else if len(s.style) > 0 {
  62. res = []string{s.style}
  63. }
  64. return
  65. }
  66. ////////////////////////////////////////////
  67. type argType uint8
  68. const (
  69. argTypeValue argType = iota
  70. argTypeRow
  71. argTypeCell
  72. )
  73. func (s argType) String() string {
  74. switch s {
  75. case argTypeRow:
  76. return "row"
  77. case argTypeCell:
  78. return "cell"
  79. default:
  80. return "value"
  81. }
  82. }
  83. func argFromIface(i interface{}) (arg CellArg, err error) {
  84. if _, check := i.(map[string]interface{}); !check {
  85. err = fmt.Errorf("Cell argument parse Error :: object expected")
  86. } else {
  87. m := JSONMap(i.(map[string]interface{}))
  88. switch m.StringVal("type", "") {
  89. case "cell":
  90. arg.aType = argTypeCell
  91. case "row":
  92. arg.aType = argTypeRow
  93. default:
  94. if m.KeyExists("value") {
  95. arg.aType = argTypeValue
  96. } else {
  97. err = fmt.Errorf("Unexpected argument type (type or value field expected)")
  98. }
  99. }
  100. delete(m, "type")
  101. arg.data = m
  102. }
  103. return
  104. }
  105. // CellArg is argument object of cell
  106. type CellArg struct {
  107. aType argType
  108. data JSONMap
  109. }
  110. func (s CellArg) String() string {
  111. return fmt.Sprintf("{ %v, data: %v }", s.aType, s.data)
  112. }
  113. // Value is getter of argument value
  114. func (s CellArg) Value() interface{} {
  115. return s.data["value"]
  116. }
  117. // Coords calculate real argument coords by current args
  118. func (s CellArg) Coords(x, y int) (dx, dy int) {
  119. dx, dy = x, y
  120. if s.data.KeyExists("x") {
  121. dx = int(s.data.Int("x", 0))
  122. } else if s.data.KeyExists("ox") {
  123. dx += int(s.data.Int("ox", 0))
  124. }
  125. if s.data.KeyExists("y") {
  126. dy = int(s.data.Int("y", 0))
  127. } else if s.data.KeyExists("oy") {
  128. dy += int(s.data.Int("oy", 0))
  129. }
  130. return
  131. }