mixed_table.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. package table
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "eta/eta_chart_lib/models"
  6. "eta/eta_chart_lib/models/data_manage"
  7. "eta/eta_chart_lib/models/request"
  8. "eta/eta_chart_lib/services/data"
  9. "eta/eta_chart_lib/utils"
  10. "fmt"
  11. "github.com/shopspring/decimal"
  12. "github.com/yidane/formula"
  13. "sort"
  14. "strconv"
  15. "strings"
  16. "time"
  17. )
  18. // BaseCalculate
  19. // @Description: 指标数据计算请求
  20. type BaseCalculate struct {
  21. DataList []*models.EdbDataList
  22. Frequency string `description:"需要转换的频度"`
  23. Formula interface{}
  24. Calendar string `description:"公历/农历"`
  25. MoveType int `description:"移动方式:1:领先(默认),2:滞后"`
  26. MoveFrequency string `description:"移动频度"`
  27. FromFrequency string `description:"来源的频度"`
  28. Source int `description:"1:累计值转月;2:累计值转季;3:同比值;4:同差值;5:N数值移动平均数计算;6:环比值;7:环差值;8:升频;9:降频;10:时间移位;11:超季节性;12:年化;13:累计值;14:累计值年初至今;15:指数修匀;16:日均值"`
  29. }
  30. // Cell
  31. // @Description: 单元格位置
  32. type Cell struct {
  33. Column int `description:"行"`
  34. Row int `description:"列"`
  35. CellInfo request.MixedTableCellDataReq `description:"对应的单元格信息"`
  36. }
  37. func GetMixedTableCellData(mixedTableReq request.MixedTableReq) (newMixedTableCellDataList [][]request.MixedTableCellDataReq, err error, errMsg string) {
  38. cellRelationConf := mixedTableReq.CellRelation
  39. config := mixedTableReq.Data
  40. // 单元格关系配置x信息
  41. cellRelationConfMap := make(map[string]request.CellRelationConf)
  42. cellRelationConfList := make([]request.CellRelationConf, 0)
  43. if cellRelationConf != `` {
  44. err = json.Unmarshal([]byte(cellRelationConf), &cellRelationConfList)
  45. if err != nil {
  46. return
  47. }
  48. for _, v := range cellRelationConfList {
  49. cellRelationConfMap[v.Key] = v
  50. }
  51. }
  52. // 找出所有的关联指标id
  53. config, edbInfoIdList, _, err, errMsg := handleConfig(config)
  54. if err != nil {
  55. return
  56. }
  57. // 查询所有关联的指标信息
  58. edbInfoList, err := data_manage.GetEdbInfoByIdList(edbInfoIdList)
  59. if err != nil {
  60. return
  61. }
  62. // 指标信息map
  63. edbInfoMap := make(map[int]*data_manage.EdbInfo)
  64. // 日度指标数据map
  65. edbDayDataListMap := make(map[int]map[string]float64)
  66. // 月度指标数据map
  67. edbMonthDataListMap := make(map[int]map[string]float64)
  68. // 日度指标数据map
  69. edbDataListMap := make(map[int][]*models.EdbDataList)
  70. for _, edbInfo := range edbInfoList {
  71. edbInfoMap[edbInfo.EdbInfoId] = edbInfo
  72. dataList := make([]*models.EdbDataList, 0)
  73. switch edbInfo.EdbInfoType {
  74. case 0:
  75. dataList, _ = models.GetEdbDataList(edbInfo.Source, edbInfo.EdbInfoId, ``, ``)
  76. case 1:
  77. _, dataList, _, _, _, _ = data.GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, ``, ``, false)
  78. default:
  79. err = errors.New(fmt.Sprint("获取失败,指标类型异常", edbInfo.EdbInfoType))
  80. }
  81. dateValMap := make(map[string]float64)
  82. monthValMap := make(map[string]float64)
  83. for _, tmpData := range dataList {
  84. // 日度数据
  85. dateValMap[tmpData.DataTime] = tmpData.Value
  86. // 月度数据(取该月份的第一个数据)
  87. yearMonth := strings.Join(strings.Split(tmpData.DataTime, "-")[0:2], "-")
  88. if _, ok := monthValMap[yearMonth]; !ok {
  89. monthValMap[yearMonth] = tmpData.Value
  90. }
  91. }
  92. edbDayDataListMap[edbInfo.EdbInfoId] = dateValMap
  93. edbMonthDataListMap[edbInfo.EdbInfoId] = monthValMap
  94. edbDataListMap[edbInfo.EdbInfoId] = dataList
  95. }
  96. // 单元格实际绑定的信息map
  97. cellDataRelationMap := make(map[string]request.MixedTableCellDataReq, 0)
  98. // 处理指定指标的日期
  99. for k, row := range config {
  100. for i, cell := range row {
  101. // 单元格是日期类型,且是日导入指标日期(指标库的最新日期)
  102. if cell.DataType == request.DateDT && cell.DataTimeType == request.EdbDateDT {
  103. if edbInfo, ok := edbInfoMap[cell.EdbInfoId]; ok {
  104. cell.ShowValue = edbInfo.EndDate
  105. cell.DataTime = edbInfo.EndDate
  106. config[k][i] = cell
  107. }
  108. }
  109. row[i] = cell
  110. cellDataRelationMap[cell.Uid] = cell
  111. }
  112. config[k] = row
  113. }
  114. // 指标计算的结果map
  115. edbSourceDataMap := make(map[string]map[string]float64)
  116. // 单元格对应的key与他的值(只处理数据类型)
  117. cellKeyVal := make(map[string]float64)
  118. // 基础计算单元格的位置信息
  119. calculateCellMap := make(map[string]Cell)
  120. calculateChainList := make([]string, 0)
  121. // 处理单元格中的数据类型(除去基础计算,因为这个是依赖于其他)
  122. for k, row := range config {
  123. for i, cell := range row {
  124. switch cell.DataType {
  125. case request.EdbDT: // 指标类型
  126. if edbInfo, ok := edbInfoMap[cell.EdbInfoId]; ok {
  127. cell.ShowValue = edbInfo.EdbName
  128. }
  129. case request.InsertDataDT, request.PopInsertDataDT: // 数据类型
  130. if cell.DataTime == `` {
  131. // 指标的最新日期
  132. if dateValList, ok := edbDataListMap[cell.EdbInfoId]; ok {
  133. tmpLenData := len(dateValList)
  134. if tmpLenData > 0 {
  135. cellKeyVal[cell.Uid] = dateValList[tmpLenData-1].Value
  136. //cell.ShowValue = utils.FormatTableDataShowValue(dateValList[tmpLenData-1].Value)
  137. cell.ShowValue = fmt.Sprint(dateValList[tmpLenData-1].Value)
  138. }
  139. }
  140. } else {
  141. tmpDateList := strings.Split(cell.DataTime, "-")
  142. tmpDateValMap := make(map[string]float64)
  143. if len(tmpDateList) == 2 {
  144. //月度数据
  145. if dateValMap, ok := edbMonthDataListMap[cell.EdbInfoId]; ok {
  146. tmpDateValMap = dateValMap
  147. }
  148. } else {
  149. // 日度数据
  150. if dateValMap, ok := edbDayDataListMap[cell.EdbInfoId]; ok {
  151. tmpDateValMap = dateValMap
  152. }
  153. }
  154. if val, ok2 := tmpDateValMap[cell.DataTime]; ok2 {
  155. //cell.ShowValue = fmt.Sprint(val)
  156. cellKeyVal[cell.Uid] = val
  157. //cell.ShowValue = utils.FormatTableDataShowValue(val)
  158. cell.ShowValue = fmt.Sprint(val)
  159. }
  160. }
  161. case request.CustomTextDT: //自定义文本
  162. if cell.Value == `` {
  163. continue
  164. }
  165. // 处理看下能否转成float,如果可以的话,说明这个也是可以参与计算的
  166. tmpDeci, tmpErr := decimal.NewFromString(cell.Value)
  167. if tmpErr == nil {
  168. tmpVal, _ := tmpDeci.Float64()
  169. cellKeyVal[cell.Uid] = tmpVal
  170. calculateCellMap[cell.Uid] = Cell{
  171. Column: k,
  172. Row: i,
  173. CellInfo: cell,
  174. }
  175. }
  176. case request.FormulateCalculateDataDT: // 公式计算(A+B这种)
  177. calculateCellMap[cell.Uid] = Cell{
  178. Column: k,
  179. Row: i,
  180. CellInfo: cell,
  181. }
  182. calculateChainList = append(calculateChainList, cell.Uid)
  183. case request.InsertEdbCalculateDataDT: // 插入指标系统计算公式生成的值
  184. // 日期
  185. var cellDateTime string
  186. // 日期关系配置不存在,则默认最新数据
  187. if relationConf, ok := cellRelationConfMap[cell.Uid]; ok {
  188. if relationConf.RelationDate.Key == `` {
  189. // 日期关系配置未绑定
  190. continue
  191. }
  192. // 配置
  193. relationCell, ok := cellDataRelationMap[relationConf.RelationDate.Key]
  194. if !ok {
  195. // 找不到对应日期的单元格
  196. continue
  197. }
  198. cellDateTime = relationCell.DataTime
  199. }
  200. var tmpDataMap map[string]float64
  201. key := utils.MD5(cell.Value)
  202. tmpDataMap, ok := edbSourceDataMap[key]
  203. if !ok {
  204. // 对应的配置值
  205. var tmpConfig request.CalculateConf
  206. err = json.Unmarshal([]byte(cell.Value), &tmpConfig)
  207. if err != nil {
  208. return
  209. }
  210. tmpDataList, ok := edbDataListMap[tmpConfig.EdbInfoId]
  211. if !ok {
  212. continue
  213. }
  214. edbInfo, ok := edbInfoMap[tmpConfig.EdbInfoId]
  215. if !ok {
  216. continue
  217. }
  218. req2 := &BaseCalculate{
  219. DataList: tmpDataList,
  220. Frequency: tmpConfig.Frequency,
  221. Formula: tmpConfig.Formula,
  222. Calendar: tmpConfig.Calendar,
  223. MoveType: tmpConfig.MoveType,
  224. MoveFrequency: tmpConfig.MoveFrequency,
  225. FromFrequency: edbInfo.Frequency,
  226. Source: tmpConfig.Source,
  227. }
  228. // 调用指标库去更新
  229. reqJson, tmpErr := json.Marshal(req2)
  230. if tmpErr != nil {
  231. utils.FileLog.Error(fmt.Sprintf("计算失败1,配置信息;%s;错误原因:%s", cell.Value, tmpErr.Error()))
  232. err = tmpErr
  233. return
  234. }
  235. respItem, tmpErr := data.BaseCalculate(string(reqJson))
  236. if tmpErr != nil {
  237. utils.FileLog.Error(fmt.Sprintf("计算失败2,配置信息;%s;错误原因:%s", cell.Value, tmpErr.Error()))
  238. err = tmpErr
  239. return
  240. }
  241. if respItem.Ret != 200 {
  242. utils.FileLog.Error(fmt.Sprintf("计算失败3,配置信息;%s;原因:%s;错误原因:%s", cell.Value, respItem.Msg, respItem.ErrMsg))
  243. continue
  244. }
  245. tmpDataMap = respItem.Data.DataMap
  246. // 计算结果存一份,万一存在重复的计算方式,那么省的重新计算一下
  247. edbSourceDataMap[key] = tmpDataMap
  248. lenDataList := len(respItem.Data.DateList)
  249. if cellDateTime == `` && lenDataList > 0 {
  250. cellDateTime = respItem.Data.DateList[lenDataList-1]
  251. }
  252. }
  253. val := tmpDataMap[cellDateTime]
  254. cellKeyVal[cell.Uid] = val
  255. //cell.ShowValue = utils.FormatTableDataShowValue(val)
  256. cell.ShowValue = fmt.Sprint(val)
  257. }
  258. row[i] = cell
  259. }
  260. config[k] = row
  261. }
  262. // 公式链计算
  263. if len(calculateChainList) > 0 {
  264. for _, cellKey := range calculateChainList {
  265. // 查找这个单元格的位置,直接map找了,而不是遍历整个单元格
  266. cellPosition, ok := calculateCellMap[cellKey]
  267. if !ok {
  268. utils.FileLog.Error("找不到单元格位置:", cellKey)
  269. continue
  270. }
  271. cell := config[cellPosition.Column][cellPosition.Row]
  272. if cell.DataType != request.FormulateCalculateDataDT { // 判断公式计算(A+B这种)类型,不是的话也过滤了
  273. continue
  274. }
  275. val, tmpErr, has := getCalculateValueByCell(calculateCellMap, cellKey, cellKeyVal)
  276. if tmpErr != nil {
  277. err = tmpErr
  278. return
  279. }
  280. if !has {
  281. continue
  282. }
  283. cellKeyVal[cell.Uid] = val
  284. //cell.ShowValue = utils.FormatTableDataShowValue(val)
  285. cell.ShowValue = fmt.Sprint(val)
  286. config[cellPosition.Column][cellPosition.Row] = cell
  287. }
  288. }
  289. newMixedTableCellDataList = config
  290. return
  291. }
  292. // getCalculateValue 获取公式计算的结果
  293. func getCalculateValueByCell(calculateCellMap map[string]Cell, key string, cellKeyValMap map[string]float64) (val float64, err error, has bool) {
  294. // 单元格的标签名
  295. val, ok := cellKeyValMap[key]
  296. if ok {
  297. has = true
  298. return
  299. }
  300. // 查找单元格数据
  301. cell, ok := calculateCellMap[key]
  302. if !ok {
  303. err = errors.New("查找单元格" + key + "的数据失败")
  304. return
  305. }
  306. colData := cell.CellInfo
  307. // 如果不是基础计算单元格,直接返回
  308. if colData.DataType != request.FormulateCalculateDataDT {
  309. return
  310. }
  311. // 如果是计算单元格
  312. tagList := make([]utils.CellPosition, 0)
  313. // 计算单元格relationCellList
  314. var relationCellList []request.RelationCell
  315. err = json.Unmarshal([]byte(colData.Extra), &relationCellList)
  316. if err != nil {
  317. return
  318. }
  319. for _, relation := range relationCellList {
  320. //relationCellTagName := strings.ToUpper(relation.Tag) + relation.Row
  321. tmpVal, tmpErr, _ := getCalculateValueByCell(calculateCellMap, relation.Key, cellKeyValMap)
  322. if tmpErr != nil {
  323. err = tmpErr
  324. return
  325. }
  326. cellKeyValMap[relation.Key] = tmpVal
  327. rowInt, tmpErr := strconv.Atoi(relation.Row)
  328. if tmpErr != nil {
  329. err = tmpErr
  330. return
  331. }
  332. tagList = append(tagList, utils.CellPosition{
  333. Tag: relation.Tag,
  334. Row: rowInt,
  335. Value: tmpVal,
  336. })
  337. }
  338. // 计算
  339. val, _, err = calculateByCellList(strings.ToUpper(colData.Value), tagList)
  340. if err != nil {
  341. return
  342. }
  343. // 重新赋值
  344. has = true
  345. cellKeyValMap[key] = val
  346. return
  347. }
  348. // handleConfig
  349. // @Description: 处理混合表格配置
  350. // @author: Roc
  351. // @datetime2023-10-27 13:24:53
  352. // @param configList [][]request.MixedTableCellDataReq
  353. // @return newConfig [][]request.MixedTableCellDataReq
  354. // @return edbInfoIdList []int
  355. // @return dataEdbInfoIdList []int
  356. // @return err error
  357. // @return errMsg string
  358. func handleConfig(configList [][]request.MixedTableCellDataReq) (newConfig [][]request.MixedTableCellDataReq, edbInfoIdList []int, dataEdbInfoIdList []int, err error, errMsg string) {
  359. edbInfoIdList = make([]int, 0)
  360. dataEdbInfoIdList = make([]int, 0)
  361. for ck, rowList := range configList {
  362. for rk, cell := range rowList {
  363. switch cell.DataType {
  364. case request.EdbDT: // 指标信息
  365. edbInfoIdList = append(edbInfoIdList, cell.EdbInfoId)
  366. case request.InsertDataDT, request.PopInsertDataDT: // 插值、弹框插值
  367. dataEdbInfoIdList = append(dataEdbInfoIdList, cell.EdbInfoId)
  368. case request.InsertEdbCalculateDataDT: // 插入指标计算公式生成的值
  369. var config request.CalculateConf
  370. err = json.Unmarshal([]byte(cell.Value), &config)
  371. if err != nil {
  372. return
  373. }
  374. edbInfoIdList = append(edbInfoIdList, config.EdbInfoId)
  375. dataEdbInfoIdList = append(dataEdbInfoIdList, cell.EdbInfoId)
  376. case request.DateDT: // 日期类型
  377. if cell.DataTimeType == request.EdbDateDT {
  378. var config request.EdbDateConf
  379. err = json.Unmarshal([]byte(cell.Value), &config)
  380. if err != nil {
  381. return
  382. }
  383. edbInfoIdList = append(edbInfoIdList, config.EdbInfoId)
  384. } else {
  385. date, tmpErr, tmpErrMsg := handleDate(cell.DataTimeType, cell.Value)
  386. if tmpErr != nil {
  387. err = tmpErr
  388. errMsg = tmpErrMsg
  389. return
  390. }
  391. rowList[rk].DataTime = date
  392. rowList[rk].ShowValue = date
  393. }
  394. }
  395. }
  396. configList[ck] = rowList
  397. }
  398. newConfig = configList
  399. return
  400. }
  401. // HandleDate
  402. // @Description: 日期处理
  403. // @author: Roc
  404. // @datetime2023-10-27 09:37:02
  405. // @param dataTimeType int
  406. // @param val string
  407. // @return date string
  408. // @return err error
  409. // @return errMsg string
  410. func HandleDate(dataTimeType int, val string) (date string, err error, errMsg string) {
  411. return handleDate(dataTimeType, val)
  412. }
  413. // handleDate
  414. // @Description: 日期处理
  415. // @author: Roc
  416. // @datetime2023-10-27 09:36:49
  417. // @param dataTimeType int
  418. // @param val string
  419. // @return date string
  420. // @return err error
  421. // @return errMsg string
  422. func handleDate(dataTimeType int, val string) (date string, err error, errMsg string) {
  423. if val == `` {
  424. errMsg = "错误的日期数据"
  425. err = errors.New(errMsg)
  426. return
  427. }
  428. switch dataTimeType {
  429. case request.CustomDateT: //手动输入日期
  430. date = val
  431. case request.SystemDateT: // 系统日期
  432. date, err, errMsg = handleSystemDateT(val)
  433. case request.EdbDateDT: // 导入指标日期(指标库的最新日期)
  434. default:
  435. errMsg = "错误的日期类型"
  436. err = errors.New(errMsg)
  437. return
  438. }
  439. return
  440. }
  441. // handleSystemDateT
  442. // @Description: 处理导入系统日期
  443. // @author: Roc
  444. // @datetime2023-10-27 09:36:21
  445. // @param confStr string
  446. // @return date string
  447. // @return err error
  448. // @return errMsg string
  449. func handleSystemDateT(confStr string) (date string, err error, errMsg string) {
  450. var config request.SystemDateConf
  451. err = json.Unmarshal([]byte(confStr), &config)
  452. if err != nil {
  453. return
  454. }
  455. switch config.Source {
  456. case request.SystemCurrDateT:
  457. date = time.Now().Format(utils.FormatDate)
  458. case request.SystemCalculateDateT:
  459. date, err, errMsg = handleSystemCalculateDateT(config.CalculateNum, config.CalculateFrequency)
  460. case request.SystemFrequencyDateT: // 处理系统日期相关的指定频率(所在周/旬/月/季/半年/年的最后/最早一天)
  461. date, err, errMsg = handleSystemAppointDateT(config.Day, config.Frequency)
  462. default:
  463. errMsg = "错误的日期日期导入方式"
  464. err = errors.New(fmt.Sprint("错误的日期日期导入方式:", config.Source))
  465. return
  466. }
  467. return
  468. }
  469. // handleSystemCalculateDateT
  470. // @Description: 处理系统日期计算后的日期
  471. // @author: Roc
  472. // @datetime2023-10-27 09:31:22
  473. // @param num int
  474. // @param frequency string
  475. // @return date string
  476. // @return err error
  477. // @return errMsg string
  478. func handleSystemCalculateDateT(num int, frequency string) (date string, err error, errMsg string) {
  479. if err != nil {
  480. return
  481. }
  482. currDate := time.Now()
  483. switch frequency {
  484. case "", "日":
  485. date = currDate.AddDate(0, 0, num).Format(utils.FormatDate)
  486. default:
  487. errMsg = "错误的日期频度:" + frequency
  488. err = errors.New(errMsg)
  489. return
  490. }
  491. return
  492. }
  493. // handleSystemAppointDateT
  494. // @Description: 处理系统日期相关的指定频率(所在周/旬/月/季/半年/年的最后/最早一天)
  495. // @author: Roc
  496. // @datetime2023-10-27 09:31:35
  497. // @param Frequency string
  498. // @param Day string
  499. // @return date string
  500. // @return err error
  501. // @return errMsg string
  502. func handleSystemAppointDateT(appointDay, frequency string) (date string, err error, errMsg string) {
  503. currDate := time.Now()
  504. switch frequency {
  505. case "本周":
  506. day := int(currDate.Weekday())
  507. if day == 0 { // 周日
  508. day = 7
  509. }
  510. num := 0
  511. switch appointDay {
  512. case "周一":
  513. num = 1
  514. case "周二":
  515. num = 2
  516. case "周三":
  517. num = 3
  518. case "周四":
  519. num = 4
  520. case "周五":
  521. num = 5
  522. case "周六":
  523. num = 6
  524. case "周日":
  525. num = 7
  526. }
  527. day = num - day
  528. date = currDate.AddDate(0, 0, day).Format(utils.FormatDate)
  529. case "本旬":
  530. day := currDate.Day()
  531. var tmpDate time.Time
  532. switch appointDay {
  533. case "第一天":
  534. if day <= 10 {
  535. tmpDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, currDate.Location())
  536. } else if day <= 20 {
  537. tmpDate = time.Date(currDate.Year(), currDate.Month(), 11, 0, 0, 0, 0, currDate.Location())
  538. } else {
  539. tmpDate = time.Date(currDate.Year(), currDate.Month(), 21, 0, 0, 0, 0, currDate.Location())
  540. }
  541. case "最后一天":
  542. if day <= 10 {
  543. tmpDate = time.Date(currDate.Year(), currDate.Month(), 10, 0, 0, 0, 0, currDate.Location())
  544. } else if day <= 20 {
  545. tmpDate = time.Date(currDate.Year(), currDate.Month(), 20, 0, 0, 0, 0, currDate.Location())
  546. } else {
  547. tmpDate = time.Date(currDate.Year(), currDate.Month()+1, 1, 0, 0, 0, 0, currDate.Location()).AddDate(0, 0, -1)
  548. }
  549. }
  550. date = tmpDate.Format(utils.FormatDate)
  551. case "本月":
  552. var tmpDate time.Time
  553. switch appointDay {
  554. case "第一天":
  555. tmpDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, currDate.Location())
  556. case "最后一天":
  557. tmpDate = time.Date(currDate.Year(), currDate.Month()+1, 1, 0, 0, 0, 0, currDate.Location()).AddDate(0, 0, -1)
  558. }
  559. date = tmpDate.Format(utils.FormatDate)
  560. case "本季":
  561. month := currDate.Month()
  562. var tmpDate time.Time
  563. switch appointDay {
  564. case "第一天":
  565. if month <= 3 {
  566. tmpDate = time.Date(currDate.Year(), 1, 1, 0, 0, 0, 0, currDate.Location())
  567. } else if month <= 6 {
  568. tmpDate = time.Date(currDate.Year(), 4, 1, 0, 0, 0, 0, currDate.Location())
  569. } else if month <= 9 {
  570. tmpDate = time.Date(currDate.Year(), 7, 1, 0, 0, 0, 0, currDate.Location())
  571. } else {
  572. tmpDate = time.Date(currDate.Year(), 10, 1, 0, 0, 0, 0, currDate.Location())
  573. }
  574. case "最后一天":
  575. if month <= 3 {
  576. tmpDate = time.Date(currDate.Year(), 3, 31, 0, 0, 0, 0, currDate.Location())
  577. } else if month <= 6 {
  578. tmpDate = time.Date(currDate.Year(), 6, 30, 0, 0, 0, 0, currDate.Location())
  579. } else if month <= 9 {
  580. tmpDate = time.Date(currDate.Year(), 9, 30, 0, 0, 0, 0, currDate.Location())
  581. } else {
  582. tmpDate = time.Date(currDate.Year(), 12, 31, 0, 0, 0, 0, currDate.Location())
  583. }
  584. }
  585. date = tmpDate.Format(utils.FormatDate)
  586. default:
  587. errMsg = "错误的日期频度:" + frequency
  588. err = errors.New(errMsg)
  589. return
  590. }
  591. return
  592. }
  593. // calculateByCellList
  594. // @Description: 根据单元格来进行公式计算
  595. // @author: Roc
  596. // @datetime2023-11-14 16:17:38
  597. // @param calculateFormula string
  598. // @param tagList []utils.CellPosition
  599. // @return calVal string
  600. // @return errMsg string
  601. // @return err error
  602. func calculateByCellList(calculateFormula string, tagList []utils.CellPosition) (calVal float64, errMsg string, err error) {
  603. if calculateFormula == "" {
  604. errMsg = "公式异常"
  605. err = errors.New(errMsg)
  606. return
  607. }
  608. calculateFormula = strings.TrimPrefix(calculateFormula, "=")
  609. calculateFormula = strings.Replace(calculateFormula, "(", "(", -1)
  610. calculateFormula = strings.Replace(calculateFormula, ")", ")", -1)
  611. calculateFormula = strings.Replace(calculateFormula, ",", ",", -1)
  612. calculateFormula = strings.Replace(calculateFormula, "。", ".", -1)
  613. calculateFormula = strings.Replace(calculateFormula, "%", "*0.01", -1)
  614. rowList := make([]int, 0)
  615. rowListMap := make(map[int][]utils.CellPosition)
  616. for _, v := range tagList {
  617. tmpRowList, ok := rowListMap[v.Row]
  618. if !ok {
  619. rowList = append(rowList, v.Row)
  620. tmpRowList = make([]utils.CellPosition, 0)
  621. }
  622. tmpRowList = append(tmpRowList, v)
  623. rowListMap[v.Row] = tmpRowList
  624. }
  625. sort.Ints(rowList)
  626. list := make([]utils.CellPosition, 0)
  627. for _, row := range rowList {
  628. list = append(list, rowListMap[row]...)
  629. }
  630. formulaFormStr := utils.ReplaceFormulaByCellList(list, calculateFormula)
  631. //计算公式异常,那么就移除该指标
  632. if formulaFormStr == `` {
  633. errMsg = "公式异常"
  634. err = errors.New(errMsg)
  635. return
  636. }
  637. expression := formula.NewExpression(formulaFormStr)
  638. calResult, err := expression.Evaluate()
  639. if err != nil {
  640. errMsg = "计算失败"
  641. err = errors.New("计算失败:Err:" + err.Error() + ";formulaStr:" + formulaFormStr)
  642. // 分母为0的报错
  643. if strings.Contains(err.Error(), "divide by zero") {
  644. errMsg = "分母不能为0"
  645. err = errors.New("分母不能为空,计算公式:" + formulaFormStr)
  646. }
  647. return
  648. }
  649. // 如果计算结果是NAN,那么就提示报错
  650. if calResult.IsNan() {
  651. errMsg = "计算失败"
  652. err = errors.New("计算失败:计算结果是:NAN;formulaStr:" + formulaFormStr)
  653. return
  654. }
  655. calVal, err = calResult.Float64()
  656. if err != nil {
  657. return
  658. }
  659. // 转Decimal然后四舍五入
  660. calVal, _ = decimal.NewFromFloat(calVal).Round(4).Float64()
  661. return
  662. }