excel_to_lucky_sheet.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. package excel
  2. import (
  3. "encoding/json"
  4. "eta_gn/eta_api/utils"
  5. "fmt"
  6. "github.com/shopspring/decimal"
  7. "github.com/xuri/excelize/v2"
  8. "sync"
  9. "time"
  10. )
  11. func ConvToLuckySheet(filePath string) (err error) {
  12. defer func() {
  13. if err != nil {
  14. fmt.Println(err)
  15. }
  16. }()
  17. f, err := excelize.OpenFile(filePath)
  18. if err != nil {
  19. fmt.Println(err)
  20. return
  21. }
  22. sheetDataList := make([]SimpleLuckySheetData, 0)
  23. sheetList := f.GetSheetList()
  24. fmt.Println("读取完成后", time.Now().Format(utils.FormatDateTime))
  25. for sheetIndex, sheetName := range sheetList {
  26. sheetData, tmpErr := getLuckySheetData(f, sheetIndex, sheetName)
  27. if tmpErr != nil {
  28. err = tmpErr
  29. return
  30. }
  31. sheetDataList = append(sheetDataList, sheetData)
  32. }
  33. byteS, err := json.Marshal(sheetDataList)
  34. if err != nil {
  35. return
  36. }
  37. utils.FileLog.Info(string(byteS))
  38. return
  39. }
  40. type SimpleLuckySheetData struct {
  41. Name string `json:"name" description:"工作表名称"`
  42. Index int `json:"index" description:"工作表索引"`
  43. CellData []SimpleLuckySheetCellData `json:"celldata" description:"单元格数据"`
  44. Config SimpleLuckySheetDataConfig `json:"config" description:""`
  45. CalcChain []CalcChain `json:"calcChain" description:"公式链"`
  46. }
  47. type CalcChain struct {
  48. Col int64 `json:"c"` //列数
  49. Row int64 `json:"r"` //行数
  50. Index int `json:"index"` //工作表id
  51. Func []interface{} `json:"func"` //公式信息,包含公式计算结果和公式字符串
  52. Color string `json:"color"` //"w":采用深度优先算法 "b":普通计算
  53. Times int `json:"times"`
  54. }
  55. type SimpleLuckySheetDataConfig struct {
  56. BorderInfo []LuckySheetDataConfigBorderInfo `json:"borderInfo" description:"边框"`
  57. Colhidden map[string]int64 `json:"colhidden" description:"隐藏列,示例值:\"colhidden\":{\"30\":0,\"31\":0}"`
  58. Merge map[string]LuckySheetDataConfigMerge `json:"merge" description:"合并单元格"`
  59. Columnlen map[string]float64 `json:"columnlen" description:"每个单元格的列宽"`
  60. }
  61. type SimpleLuckySheetCellData struct {
  62. Col int64 `json:"c" description:"列"`
  63. Row int64 `json:"r" description:"行"`
  64. Value interface{} `json:"v" description:"单元格内值的数据"`
  65. }
  66. type SimpleLuckySheetDataValue struct {
  67. CellType LuckySheetDataCellType `json:"ct" description:"单元格值格式:文本、时间等 "`
  68. Value interface{} `json:"v" description:"原始值"`
  69. Function string `json:"f" description:"公式"`
  70. }
  71. func getLuckySheetData(f *excelize.File, sheetIndex int, sheetName string) (sheetData SimpleLuckySheetData, err error) {
  72. cellData := make([]SimpleLuckySheetCellData, 0) // excel数据
  73. mergeData := make(map[string]LuckySheetDataConfigMerge) //合并单元格数据
  74. calcChainList := make([]CalcChain, 0) //公式链信息
  75. sheetData = SimpleLuckySheetData{
  76. Name: sheetName,
  77. Index: sheetIndex,
  78. CellData: cellData,
  79. Config: SimpleLuckySheetDataConfig{},
  80. }
  81. fmt.Println("开始读取sheet数据:", time.Now().Format(utils.FormatDateTime))
  82. rows, tmpErr := f.GetRows(sheetName)
  83. if tmpErr != nil {
  84. err = tmpErr
  85. return
  86. }
  87. fmt.Println("读取完sheet数据:", time.Now().Format(utils.FormatDateTime))
  88. lenRow := len(rows)
  89. fmt.Println("总共:", lenRow, "条数据")
  90. if lenRow <= 0 {
  91. return
  92. }
  93. maxColumnIndex := 0
  94. wg := sync.WaitGroup{}
  95. wg.Add(1)
  96. go func() {
  97. defer func() {
  98. wg.Done()
  99. }()
  100. mergeCellList, err := f.GetMergeCells(sheetName)
  101. if err != nil {
  102. return
  103. }
  104. for _, v := range mergeCellList {
  105. cStartIndex, rStartIndex, tmpErr := excelize.CellNameToCoordinates(v.GetStartAxis())
  106. if tmpErr != nil {
  107. err = tmpErr
  108. return
  109. }
  110. cEndIndex, rEndIndex, tmpErr := excelize.CellNameToCoordinates(v.GetEndAxis())
  111. if tmpErr != nil {
  112. err = tmpErr
  113. return
  114. }
  115. tmpLuckySheetDataConfigMerge := LuckySheetDataConfigMerge{
  116. Row: rStartIndex - 1,
  117. Column: cStartIndex - 1,
  118. Rs: rEndIndex - rStartIndex + 1,
  119. Cs: cEndIndex - cStartIndex + 1,
  120. }
  121. mergeData[fmt.Sprint(rStartIndex-1, "_", cStartIndex-1)] = tmpLuckySheetDataConfigMerge
  122. }
  123. sheetData.Config.Merge = mergeData
  124. }()
  125. colWidthMap := make(map[string]float64)
  126. splitNum := 500
  127. splitLen := lenRow / splitNum
  128. residue := lenRow % splitNum
  129. if residue > 0 {
  130. splitLen += 1
  131. }
  132. for i := 0; i < splitLen; i++ {
  133. wg.Add(1)
  134. startRow := i * splitNum
  135. endRow := (i + 1) * splitNum
  136. if i == splitLen-1 && residue > 0 {
  137. endRow = lenRow
  138. }
  139. go func(currStartRow, currEndRow int) {
  140. defer func() {
  141. wg.Done()
  142. }()
  143. for rIndex := currStartRow; rIndex < currEndRow; rIndex++ {
  144. row := rows[rIndex]
  145. for cIndex, colCell := range row {
  146. if rIndex == 0 {
  147. }
  148. if maxColumnIndex < cIndex {
  149. maxColumnIndex = cIndex
  150. }
  151. cellName, tmpErr := excelize.CoordinatesToCellName(cIndex+1, rIndex+1)
  152. if tmpErr != nil {
  153. err = tmpErr
  154. return
  155. }
  156. cellFormula, tmpErr := f.GetCellFormula(sheetName, cellName)
  157. if tmpErr != nil {
  158. err = tmpErr
  159. return
  160. }
  161. var colCellIntfac interface{}
  162. cellTypeT := "g"
  163. tmpDec, tmpErr := decimal.NewFromString(colCell)
  164. if tmpErr != nil {
  165. colCellIntfac = colCell
  166. } else {
  167. colCellIntfac, _ = tmpDec.Float64()
  168. cellTypeT = "n"
  169. }
  170. if cellFormula != `` {
  171. cellFormula = `=` + cellFormula
  172. calcChainList = append(calcChainList, CalcChain{
  173. Col: int64(cIndex),
  174. Row: int64(rIndex),
  175. Index: sheetIndex,
  176. Func: []interface{}{true, colCell, cellFormula},
  177. Color: "w",
  178. Times: 0,
  179. })
  180. }
  181. valueMap := make(map[string]interface{})
  182. valueMap["ct"] = LuckySheetDataCellType{
  183. Fa: "General",
  184. T: cellTypeT,
  185. }
  186. valueMap["v"] = colCellIntfac
  187. if cellFormula != `` {
  188. valueMap["f"] = cellFormula
  189. }
  190. cellData = append(cellData, SimpleLuckySheetCellData{
  191. Col: int64(cIndex),
  192. Row: int64(rIndex),
  193. Value: valueMap,
  194. })
  195. }
  196. }
  197. }(startRow, endRow)
  198. }
  199. wg.Wait()
  200. fmt.Println("解析完sheet数据:", time.Now().Format(utils.FormatDateTime))
  201. sheetData.Config.Columnlen = colWidthMap
  202. sheetData.CellData = cellData
  203. sheetData.CalcChain = calcChainList
  204. return
  205. }
  206. func emuToPx(num float64) float64 {
  207. return num * 15
  208. }