pivotTable_test.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. package excelize
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "path/filepath"
  6. "strings"
  7. "testing"
  8. "github.com/stretchr/testify/assert"
  9. )
  10. func TestAddPivotTable(t *testing.T) {
  11. f := NewFile()
  12. // Create some data in a sheet
  13. month := []string{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}
  14. year := []int{2017, 2018, 2019}
  15. types := []string{"Meat", "Dairy", "Beverages", "Produce"}
  16. region := []string{"East", "West", "North", "South"}
  17. assert.NoError(t, f.SetSheetRow("Sheet1", "A1", &[]string{"Month", "Year", "Type", "Sales", "Region"}))
  18. for i := 0; i < 30; i++ {
  19. assert.NoError(t, f.SetCellValue("Sheet1", fmt.Sprintf("A%d", i+2), month[rand.Intn(12)]))
  20. assert.NoError(t, f.SetCellValue("Sheet1", fmt.Sprintf("B%d", i+2), year[rand.Intn(3)]))
  21. assert.NoError(t, f.SetCellValue("Sheet1", fmt.Sprintf("C%d", i+2), types[rand.Intn(4)]))
  22. assert.NoError(t, f.SetCellValue("Sheet1", fmt.Sprintf("D%d", i+2), rand.Intn(5000)))
  23. assert.NoError(t, f.SetCellValue("Sheet1", fmt.Sprintf("E%d", i+2), region[rand.Intn(4)]))
  24. }
  25. assert.NoError(t, f.AddPivotTable(&PivotTableOption{
  26. DataRange: "Sheet1!$A$1:$E$31",
  27. PivotTableRange: "Sheet1!$G$2:$M$34",
  28. Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
  29. Filter: []PivotTableField{{Data: "Region"}},
  30. Columns: []PivotTableField{{Data: "Type", DefaultSubtotal: true}},
  31. Data: []PivotTableField{{Data: "Sales", Subtotal: "Sum", Name: "Summarize by Sum"}},
  32. RowGrandTotals: true,
  33. ColGrandTotals: true,
  34. ShowDrill: true,
  35. ShowRowHeaders: true,
  36. ShowColHeaders: true,
  37. ShowLastColumn: true,
  38. }))
  39. // Use different order of coordinate tests
  40. assert.NoError(t, f.AddPivotTable(&PivotTableOption{
  41. DataRange: "Sheet1!$A$1:$E$31",
  42. PivotTableRange: "Sheet1!$U$34:$O$2",
  43. Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
  44. Columns: []PivotTableField{{Data: "Type", DefaultSubtotal: true}},
  45. Data: []PivotTableField{{Data: "Sales", Subtotal: "Average", Name: "Summarize by Average"}},
  46. RowGrandTotals: true,
  47. ColGrandTotals: true,
  48. ShowDrill: true,
  49. ShowRowHeaders: true,
  50. ShowColHeaders: true,
  51. ShowLastColumn: true,
  52. }))
  53. assert.NoError(t, f.AddPivotTable(&PivotTableOption{
  54. DataRange: "Sheet1!$A$1:$E$31",
  55. PivotTableRange: "Sheet1!$W$2:$AC$34",
  56. Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
  57. Columns: []PivotTableField{{Data: "Region"}},
  58. Data: []PivotTableField{{Data: "Sales", Subtotal: "Count", Name: "Summarize by Count"}},
  59. RowGrandTotals: true,
  60. ColGrandTotals: true,
  61. ShowDrill: true,
  62. ShowRowHeaders: true,
  63. ShowColHeaders: true,
  64. ShowLastColumn: true,
  65. }))
  66. assert.NoError(t, f.AddPivotTable(&PivotTableOption{
  67. DataRange: "Sheet1!$A$1:$E$31",
  68. PivotTableRange: "Sheet1!$G$37:$W$50",
  69. Rows: []PivotTableField{{Data: "Month"}},
  70. Columns: []PivotTableField{{Data: "Region", DefaultSubtotal: true}, {Data: "Year"}},
  71. Data: []PivotTableField{{Data: "Sales", Subtotal: "CountNums", Name: "Summarize by CountNums"}},
  72. RowGrandTotals: true,
  73. ColGrandTotals: true,
  74. ShowDrill: true,
  75. ShowRowHeaders: true,
  76. ShowColHeaders: true,
  77. ShowLastColumn: true,
  78. }))
  79. assert.NoError(t, f.AddPivotTable(&PivotTableOption{
  80. DataRange: "Sheet1!$A$1:$E$31",
  81. PivotTableRange: "Sheet1!$AE$2:$AG$33",
  82. Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
  83. Data: []PivotTableField{{Data: "Sales", Subtotal: "Max", Name: "Summarize by Max"}, {Data: "Sales", Subtotal: "Average", Name: "Average of Sales"}},
  84. RowGrandTotals: true,
  85. ColGrandTotals: true,
  86. ShowDrill: true,
  87. ShowRowHeaders: true,
  88. ShowColHeaders: true,
  89. ShowLastColumn: true,
  90. }))
  91. // Create pivot table with empty subtotal field name and specified style
  92. assert.NoError(t, f.AddPivotTable(&PivotTableOption{
  93. DataRange: "Sheet1!$A$1:$E$31",
  94. PivotTableRange: "Sheet1!$AJ$2:$AP1$35",
  95. Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
  96. Filter: []PivotTableField{{Data: "Region"}},
  97. Columns: []PivotTableField{},
  98. Data: []PivotTableField{{Subtotal: "Sum", Name: "Summarize by Sum"}},
  99. RowGrandTotals: true,
  100. ColGrandTotals: true,
  101. ShowDrill: true,
  102. ShowRowHeaders: true,
  103. ShowColHeaders: true,
  104. ShowLastColumn: true,
  105. PivotTableStyleName: "PivotStyleLight19",
  106. }))
  107. f.NewSheet("Sheet2")
  108. assert.NoError(t, f.AddPivotTable(&PivotTableOption{
  109. DataRange: "Sheet1!$A$1:$E$31",
  110. PivotTableRange: "Sheet2!$A$1:$AR$15",
  111. Rows: []PivotTableField{{Data: "Month"}},
  112. Columns: []PivotTableField{{Data: "Region", DefaultSubtotal: true}, {Data: "Type", DefaultSubtotal: true}, {Data: "Year"}},
  113. Data: []PivotTableField{{Data: "Sales", Subtotal: "Min", Name: "Summarize by Min"}},
  114. RowGrandTotals: true,
  115. ColGrandTotals: true,
  116. ShowDrill: true,
  117. ShowRowHeaders: true,
  118. ShowColHeaders: true,
  119. ShowLastColumn: true,
  120. }))
  121. assert.NoError(t, f.AddPivotTable(&PivotTableOption{
  122. DataRange: "Sheet1!$A$1:$E$31",
  123. PivotTableRange: "Sheet2!$A$18:$AR$54",
  124. Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Type"}},
  125. Columns: []PivotTableField{{Data: "Region", DefaultSubtotal: true}, {Data: "Year"}},
  126. Data: []PivotTableField{{Data: "Sales", Subtotal: "Product", Name: "Summarize by Product"}},
  127. RowGrandTotals: true,
  128. ColGrandTotals: true,
  129. ShowDrill: true,
  130. ShowRowHeaders: true,
  131. ShowColHeaders: true,
  132. ShowLastColumn: true,
  133. }))
  134. // Test empty pivot table options
  135. assert.EqualError(t, f.AddPivotTable(nil), "parameter is required")
  136. // Test invalid data range
  137. assert.EqualError(t, f.AddPivotTable(&PivotTableOption{
  138. DataRange: "Sheet1!$A$1:$A$1",
  139. PivotTableRange: "Sheet1!$U$34:$O$2",
  140. Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
  141. Columns: []PivotTableField{{Data: "Type", DefaultSubtotal: true}},
  142. Data: []PivotTableField{{Data: "Sales"}},
  143. }), `parameter 'DataRange' parsing error: parameter is invalid`)
  144. // Test the data range of the worksheet that is not declared
  145. assert.EqualError(t, f.AddPivotTable(&PivotTableOption{
  146. DataRange: "$A$1:$E$31",
  147. PivotTableRange: "Sheet1!$U$34:$O$2",
  148. Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
  149. Columns: []PivotTableField{{Data: "Type", DefaultSubtotal: true}},
  150. Data: []PivotTableField{{Data: "Sales"}},
  151. }), `parameter 'DataRange' parsing error: parameter is invalid`)
  152. // Test the worksheet declared in the data range does not exist
  153. assert.EqualError(t, f.AddPivotTable(&PivotTableOption{
  154. DataRange: "SheetN!$A$1:$E$31",
  155. PivotTableRange: "Sheet1!$U$34:$O$2",
  156. Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
  157. Columns: []PivotTableField{{Data: "Type", DefaultSubtotal: true}},
  158. Data: []PivotTableField{{Data: "Sales"}},
  159. }), "sheet SheetN is not exist")
  160. // Test the pivot table range of the worksheet that is not declared
  161. assert.EqualError(t, f.AddPivotTable(&PivotTableOption{
  162. DataRange: "Sheet1!$A$1:$E$31",
  163. PivotTableRange: "$U$34:$O$2",
  164. Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
  165. Columns: []PivotTableField{{Data: "Type", DefaultSubtotal: true}},
  166. Data: []PivotTableField{{Data: "Sales"}},
  167. }), `parameter 'PivotTableRange' parsing error: parameter is invalid`)
  168. // Test the worksheet declared in the pivot table range does not exist
  169. assert.EqualError(t, f.AddPivotTable(&PivotTableOption{
  170. DataRange: "Sheet1!$A$1:$E$31",
  171. PivotTableRange: "SheetN!$U$34:$O$2",
  172. Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
  173. Columns: []PivotTableField{{Data: "Type", DefaultSubtotal: true}},
  174. Data: []PivotTableField{{Data: "Sales"}},
  175. }), "sheet SheetN is not exist")
  176. // Test not exists worksheet in data range
  177. assert.EqualError(t, f.AddPivotTable(&PivotTableOption{
  178. DataRange: "SheetN!$A$1:$E$31",
  179. PivotTableRange: "Sheet1!$U$34:$O$2",
  180. Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
  181. Columns: []PivotTableField{{Data: "Type", DefaultSubtotal: true}},
  182. Data: []PivotTableField{{Data: "Sales"}},
  183. }), "sheet SheetN is not exist")
  184. // Test invalid row number in data range
  185. assert.EqualError(t, f.AddPivotTable(&PivotTableOption{
  186. DataRange: "Sheet1!$A$0:$E$31",
  187. PivotTableRange: "Sheet1!$U$34:$O$2",
  188. Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
  189. Columns: []PivotTableField{{Data: "Type", DefaultSubtotal: true}},
  190. Data: []PivotTableField{{Data: "Sales"}},
  191. }), `parameter 'DataRange' parsing error: cannot convert cell "A0" to coordinates: invalid cell name "A0"`)
  192. assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAddPivotTable1.xlsx")))
  193. // Test with field names that exceed the length limit and invalid subtotal
  194. assert.NoError(t, f.AddPivotTable(&PivotTableOption{
  195. DataRange: "Sheet1!$A$1:$E$31",
  196. PivotTableRange: "Sheet1!$G$2:$M$34",
  197. Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
  198. Columns: []PivotTableField{{Data: "Type", DefaultSubtotal: true}},
  199. Data: []PivotTableField{{Data: "Sales", Subtotal: "-", Name: strings.Repeat("s", 256)}},
  200. }))
  201. // Test adjust range with invalid range
  202. _, _, err := f.adjustRange("")
  203. assert.EqualError(t, err, "parameter is required")
  204. // Test get pivot fields order with empty data range
  205. _, err = f.getPivotFieldsOrder("")
  206. assert.EqualError(t, err, `parameter 'DataRange' parsing error: parameter is required`)
  207. // Test add pivot cache with empty data range
  208. assert.EqualError(t, f.addPivotCache(0, "", &PivotTableOption{}, nil), "parameter 'DataRange' parsing error: parameter is required")
  209. // Test add pivot cache with invalid data range
  210. assert.EqualError(t, f.addPivotCache(0, "", &PivotTableOption{
  211. DataRange: "$A$1:$E$31",
  212. PivotTableRange: "Sheet1!$U$34:$O$2",
  213. Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
  214. Columns: []PivotTableField{{Data: "Type", DefaultSubtotal: true}},
  215. Data: []PivotTableField{{Data: "Sales"}},
  216. }, nil), "parameter 'DataRange' parsing error: parameter is invalid")
  217. // Test add pivot table with empty options
  218. assert.EqualError(t, f.addPivotTable(0, 0, "", &PivotTableOption{}), "parameter 'PivotTableRange' parsing error: parameter is required")
  219. // Test add pivot table with invalid data range
  220. assert.EqualError(t, f.addPivotTable(0, 0, "", &PivotTableOption{}), "parameter 'PivotTableRange' parsing error: parameter is required")
  221. // Test add pivot fields with empty data range
  222. assert.EqualError(t, f.addPivotFields(nil, &PivotTableOption{
  223. DataRange: "$A$1:$E$31",
  224. PivotTableRange: "Sheet1!$U$34:$O$2",
  225. Rows: []PivotTableField{{Data: "Month", DefaultSubtotal: true}, {Data: "Year"}},
  226. Columns: []PivotTableField{{Data: "Type", DefaultSubtotal: true}},
  227. Data: []PivotTableField{{Data: "Sales"}},
  228. }), `parameter 'DataRange' parsing error: parameter is invalid`)
  229. // Test get pivot fields index with empty data range
  230. _, err = f.getPivotFieldsIndex([]PivotTableField{}, &PivotTableOption{})
  231. assert.EqualError(t, err, `parameter 'DataRange' parsing error: parameter is required`)
  232. }
  233. func TestAddPivotRowFields(t *testing.T) {
  234. f := NewFile()
  235. // Test invalid data range
  236. assert.EqualError(t, f.addPivotRowFields(&xlsxPivotTableDefinition{}, &PivotTableOption{
  237. DataRange: "Sheet1!$A$1:$A$1",
  238. }), `parameter 'DataRange' parsing error: parameter is invalid`)
  239. }
  240. func TestAddPivotPageFields(t *testing.T) {
  241. f := NewFile()
  242. // Test invalid data range
  243. assert.EqualError(t, f.addPivotPageFields(&xlsxPivotTableDefinition{}, &PivotTableOption{
  244. DataRange: "Sheet1!$A$1:$A$1",
  245. }), `parameter 'DataRange' parsing error: parameter is invalid`)
  246. }
  247. func TestAddPivotDataFields(t *testing.T) {
  248. f := NewFile()
  249. // Test invalid data range
  250. assert.EqualError(t, f.addPivotDataFields(&xlsxPivotTableDefinition{}, &PivotTableOption{
  251. DataRange: "Sheet1!$A$1:$A$1",
  252. }), `parameter 'DataRange' parsing error: parameter is invalid`)
  253. }
  254. func TestAddPivotColFields(t *testing.T) {
  255. f := NewFile()
  256. // Test invalid data range
  257. assert.EqualError(t, f.addPivotColFields(&xlsxPivotTableDefinition{}, &PivotTableOption{
  258. DataRange: "Sheet1!$A$1:$A$1",
  259. Columns: []PivotTableField{{Data: "Type", DefaultSubtotal: true}},
  260. }), `parameter 'DataRange' parsing error: parameter is invalid`)
  261. }
  262. func TestGetPivotFieldsOrder(t *testing.T) {
  263. f := NewFile()
  264. // Test get pivot fields order with not exist worksheet
  265. _, err := f.getPivotFieldsOrder("SheetN!$A$1:$E$31")
  266. assert.EqualError(t, err, "sheet SheetN is not exist")
  267. }
  268. func TestInStrSlice(t *testing.T) {
  269. assert.EqualValues(t, -1, inStrSlice([]string{}, ""))
  270. }
  271. func TestGetPivotTableFieldName(t *testing.T) {
  272. f := NewFile()
  273. f.getPivotTableFieldName("-", []PivotTableField{})
  274. }