base_from_fenwei.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. package services
  2. import (
  3. "encoding/json"
  4. "eta/eta_data_analysis/models"
  5. "eta/eta_data_analysis/utils"
  6. "fmt"
  7. "github.com/shakinm/xlsReader/xls"
  8. "github.com/xuri/excelize/v2"
  9. "path"
  10. "strings"
  11. "time"
  12. )
  13. const (
  14. FenWeiIndexNamePrefix = "fwsj" // 指标名称前缀
  15. FenWeiExcelHistoryNameA = "动力煤产销存-66家"
  16. FenWeiExcelHistoryNameB = "动力煤产销存-100家"
  17. FenWeiExcelHistoryNameC = "焦煤产销存-53家"
  18. FenWeiExcelHistoryNameD = "焦煤产销存-88家"
  19. FenWeiExcelHistoryNameE = "样本焦化厂焦煤"
  20. FenWeiYangBenIndexNamePre = "样本焦企炼焦煤库存可用天数"
  21. FenWeiYangBenIndexClassifyId = 5
  22. )
  23. var FenWeiProvinces = []string{
  24. "内蒙古", "山西", "陕西", "三省合计", "临汾市", "临汾", "吕梁市", "吕梁", "长治市", "长治", "山西其他", "河北", "合计",
  25. }
  26. // FenWeiProvinceClassifyMapping 指标名称省份->分类省份
  27. var FenWeiProvinceClassifyMapping = map[string]string{
  28. "内蒙古": "内蒙古",
  29. "山西": "山西",
  30. "陕西": "陕西",
  31. "三省合计": "三省合计",
  32. "临汾市": "临汾市",
  33. "吕梁市": "吕梁市",
  34. "长治市": "长治市",
  35. "临汾": "临汾市",
  36. "吕梁": "吕梁市",
  37. "长治": "长治市",
  38. "山西其他": "山西其他",
  39. "河北": "河北",
  40. "合计": "合计",
  41. }
  42. // FenWeiFirstClassifyMap excel表名->一级分类ID
  43. var FenWeiFirstClassifyMap = map[string]int{
  44. FenWeiExcelHistoryNameA: 1,
  45. FenWeiExcelHistoryNameB: 2,
  46. FenWeiExcelHistoryNameC: 3,
  47. FenWeiExcelHistoryNameD: 4,
  48. FenWeiExcelHistoryNameE: 5,
  49. }
  50. // AnalysisFenWeiHistoryExcel 解析汾渭历史Excel数据
  51. func AnalysisFenWeiHistoryExcel(filePath string) (err error) {
  52. defer func() {
  53. if err != nil {
  54. fmt.Printf("AnalysisFenWeiExcel ErrMsg: %s\n", err.Error())
  55. utils.FileLog.Info(fmt.Sprintf("AnalysisFenWeiExcel ErrMsg: %s", err.Error()))
  56. }
  57. }()
  58. fileName := path.Base(filePath)
  59. var indexes []*models.FenWeiExcelIndex
  60. var e error
  61. if strings.Contains(fileName, FenWeiExcelHistoryNameA) {
  62. indexes, e = AnalysisFenWeiHistoryExcelNormal(filePath, FenWeiExcelHistoryNameA)
  63. } else if strings.Contains(fileName, FenWeiExcelHistoryNameB) {
  64. indexes, e = AnalysisFenWeiHistoryExcelNormal(filePath, FenWeiExcelHistoryNameB)
  65. } else if strings.Contains(fileName, FenWeiExcelHistoryNameC) {
  66. indexes, e = AnalysisFenWeiHistoryExcelNormal(filePath, FenWeiExcelHistoryNameC)
  67. } else if strings.Contains(fileName, FenWeiExcelHistoryNameD) {
  68. indexes, e = AnalysisFenWeiHistoryExcelNormal(filePath, FenWeiExcelHistoryNameD)
  69. } else if strings.Contains(fileName, FenWeiExcelHistoryNameE) {
  70. indexes, e = AnalysisFenWeiExcelYangBen(filePath)
  71. } else {
  72. utils.FileLog.Info(fmt.Sprintf("文件名有误, FileName: %s", fileName))
  73. return
  74. }
  75. if e != nil {
  76. utils.FileLog.Info(fmt.Sprintf("获取excel数据失败, FileName: %s, Err: %s", fileName, e))
  77. return
  78. }
  79. if len(indexes) == 0 {
  80. utils.FileLog.Info(fmt.Sprintf("fileName: %s, index empty", fileName))
  81. return
  82. }
  83. // 写入数据
  84. params := make(map[string]interface{})
  85. params["List"] = indexes
  86. params["TerminalCode"] = utils.FenweiTerminalCode
  87. result, e := PostEdbLib(params, utils.LIB_ROUTE_FENWEI_HANDLE)
  88. if e != nil {
  89. b, _ := json.Marshal(params)
  90. utils.FileLog.Info(fmt.Sprintf("fileName: %s, PostEdbLib err: %s, params: %s", fileName, e.Error(), string(b)))
  91. return
  92. }
  93. resp := new(models.BaseEdbLibResponse)
  94. if e := json.Unmarshal(result, &resp); e != nil {
  95. utils.FileLog.Info(fmt.Sprintf("fileName: %s, json.Unmarshal err: %s", fileName, e.Error()))
  96. return
  97. }
  98. if resp.Ret != 200 {
  99. utils.FileLog.Info(fmt.Sprintf("fileName: %s, Msg: %s, ErrMsg: %s", fileName, resp.Msg, resp.ErrMsg))
  100. return
  101. }
  102. return
  103. }
  104. // AnalysisFenWeiHistoryExcelNormal 历史数据-动力煤产销存/焦煤产销存
  105. func AnalysisFenWeiHistoryExcelNormal(filePath, excelName string) (indexes []*models.FenWeiExcelIndex, err error) {
  106. defer func() {
  107. if err != nil {
  108. fmt.Printf("AnalysisFenWeiHistoryExcelNormal ErrMsg: %s\n", err.Error())
  109. utils.FileLog.Info(fmt.Sprintf("AnalysisFenWeiHistoryExcelNormal ErrMsg: %s", err.Error()))
  110. }
  111. }()
  112. f, e := excelize.OpenFile(filePath)
  113. if e != nil {
  114. err = fmt.Errorf("open file err: %s", e.Error())
  115. return
  116. }
  117. defer func() {
  118. if e = f.Close(); e != nil {
  119. err = fmt.Errorf("f close err: %s", e.Error())
  120. }
  121. }()
  122. sheetName := f.GetSheetName(0)
  123. rows, e := f.GetRows(sheetName)
  124. if e != nil {
  125. err = fmt.Errorf("f GetRows err: %s", e.Error())
  126. return
  127. }
  128. // 获取指标分类
  129. firstId := FenWeiFirstClassifyMap[excelName]
  130. if firstId <= 0 {
  131. err = fmt.Errorf("excel名称有误, 分类不匹配, excelName: %s", excelName)
  132. return
  133. }
  134. classifies, e := GetFenWeiClassify()
  135. if e != nil {
  136. err = fmt.Errorf("获取指标分类失败, Err: %s", e.Error())
  137. return
  138. }
  139. secondClassifyMap := make(map[string]int)
  140. for _, v := range classifies {
  141. if v.ClassifyId != firstId {
  142. continue
  143. }
  144. for _, c := range v.Child {
  145. secondClassifyMap[c.ClassifyName] = c.ClassifyId
  146. }
  147. }
  148. indexes = make([]*models.FenWeiExcelIndex, 0)
  149. indexColIndex := make(map[int]*models.FenWeiExcelIndex) // 列对应的指标(B列-?列)
  150. for i, row := range rows {
  151. // 首行为标题, 忽略
  152. if i == 0 {
  153. continue
  154. }
  155. // 第二行-指标名称
  156. if i == 1 {
  157. for k, cell := range row {
  158. if k == 0 {
  159. continue
  160. }
  161. name := strings.TrimSpace(cell)
  162. if name == "" {
  163. break
  164. }
  165. if indexColIndex[k] == nil {
  166. indexColIndex[k] = new(models.FenWeiExcelIndex)
  167. indexColIndex[k].ExcelDataMap = make(map[string]string)
  168. indexColIndex[k].TerminalCode = utils.TerminalCode
  169. }
  170. indexColIndex[k].IndexName = name
  171. }
  172. continue
  173. }
  174. // 第三行-指标ID、指标分类
  175. if i == 2 {
  176. for k := range row {
  177. if k == 0 {
  178. continue
  179. }
  180. if indexColIndex[k] == nil {
  181. utils.FileLog.Info(fmt.Sprintf("第%d列无指标ID", k))
  182. break
  183. }
  184. // 例:内蒙古煤矿数量/动力煤/66家样本->fwsjneimenggumksldlm66jyb
  185. name := strings.ReplaceAll(indexColIndex[k].IndexName, "/", "")
  186. var middle, suffix, province string
  187. for _, p := range FenWeiProvinces {
  188. if strings.Contains(name, p) {
  189. province = p
  190. middle = utils.GetFullPingYin(p)
  191. name = strings.ReplaceAll(name, p, "")
  192. break
  193. }
  194. }
  195. if middle == "" {
  196. utils.FileLog.Info(fmt.Sprintf("指标名称转换编码有误, IndexName: %s", indexColIndex[k].IndexName))
  197. continue
  198. }
  199. classifyProvince := FenWeiProvinceClassifyMapping[province]
  200. classifyId := secondClassifyMap[classifyProvince]
  201. if classifyId <= 0 {
  202. utils.FileLog.Info(fmt.Sprintf("指标名称分类不匹配, IndexName: %s", indexColIndex[k].IndexName))
  203. continue
  204. }
  205. suffix = utils.GetFirstPingYin(name)
  206. indexColIndex[k].IndexCode = fmt.Sprint(FenWeiIndexNamePrefix, middle, suffix)
  207. indexColIndex[k].ClassifyId = classifyId
  208. }
  209. continue
  210. }
  211. // 第四行-频度
  212. if i == 3 {
  213. for k, cell := range row {
  214. if k == 0 {
  215. continue
  216. }
  217. if indexColIndex[k] == nil {
  218. utils.FileLog.Info(fmt.Sprintf("第%d列无指标名称", k))
  219. break
  220. }
  221. frequency := strings.TrimSpace(cell)
  222. indexColIndex[k].Frequency = frequency
  223. }
  224. continue
  225. }
  226. // 第五行-单位
  227. if i == 4 {
  228. for k, cell := range row {
  229. if k == 0 {
  230. continue
  231. }
  232. if indexColIndex[k] == nil {
  233. utils.FileLog.Info(fmt.Sprintf("第%d列无指标单位", k))
  234. break
  235. }
  236. unit := strings.TrimSpace(cell)
  237. indexColIndex[k].Unit = unit
  238. }
  239. continue
  240. }
  241. // 数据行
  242. if i > 4 {
  243. var date string
  244. for k, cell := range row {
  245. if k == 0 {
  246. // 日期
  247. date = strings.TrimSpace(cell)
  248. _, e := time.Parse(utils.FormatDate, date)
  249. if e != nil {
  250. // 如果第一列不是日期那么结束本行的读取
  251. break
  252. }
  253. continue
  254. }
  255. // 日期数据
  256. if date == "" {
  257. utils.FileLog.Info(fmt.Sprintf("第%d行无数据日期", i))
  258. break
  259. }
  260. if indexColIndex[k] == nil {
  261. utils.FileLog.Info(fmt.Sprintf("第%d列无指标名称", k))
  262. break
  263. }
  264. val := strings.TrimSpace(cell)
  265. if val == "" {
  266. // 单元格数据为空, 则当前日期无数据
  267. continue
  268. }
  269. indexColIndex[k].ExcelDataMap[date] = val
  270. }
  271. continue
  272. }
  273. }
  274. for _, v := range indexColIndex {
  275. if v.IndexCode == "" {
  276. continue
  277. }
  278. indexes = append(indexes, v)
  279. }
  280. return
  281. }
  282. // AnalysisFenWeiExcelYangBen 样本焦化厂
  283. func AnalysisFenWeiExcelYangBen(filePath string) (indexes []*models.FenWeiExcelIndex, err error) {
  284. defer func() {
  285. if err != nil {
  286. fmt.Printf("AnalysisFenWeiExcelYangBen ErrMsg: %s\n", err.Error())
  287. utils.FileLog.Info(fmt.Sprintf("AnalysisFenWeiExcelYangBen ErrMsg: %s", err.Error()))
  288. }
  289. }()
  290. indexColIndex := make(map[int]*models.FenWeiExcelIndex) // 列对应的指标(B列-E列)
  291. provinces := []string{"地区", "全国", "山西", "河北", "山东"}
  292. for k, v := range provinces {
  293. if k == 0 {
  294. continue
  295. }
  296. if indexColIndex[k] == nil {
  297. indexColIndex[k] = new(models.FenWeiExcelIndex)
  298. indexColIndex[k].ExcelDataMap = make(map[string]string)
  299. indexColIndex[k].TerminalCode = utils.TerminalCode
  300. indexColIndex[k].ClassifyId = FenWeiYangBenIndexClassifyId
  301. indexColIndex[k].Frequency = "周度"
  302. indexColIndex[k].Unit = "天"
  303. indexColIndex[k].IndexName = fmt.Sprintf("%s/%s", FenWeiYangBenIndexNamePre, v)
  304. // 指标编码, 例:样本焦企炼焦煤库存可用天数/全国->fwsjybjqljmkckytsquanguo
  305. name := strings.ReplaceAll(indexColIndex[k].IndexName, "/", "")
  306. var middle, suffix string
  307. for _, p := range provinces {
  308. if strings.Contains(name, p) {
  309. suffix = utils.GetFullPingYin(p)
  310. name = strings.ReplaceAll(name, p, "")
  311. break
  312. }
  313. }
  314. if suffix == "" {
  315. utils.FileLog.Info(fmt.Sprintf("指标名称转换编码有误, IndexName: %s", indexColIndex[k].IndexName))
  316. continue
  317. }
  318. middle = utils.GetFirstPingYin(name)
  319. indexColIndex[k].IndexCode = fmt.Sprint(FenWeiIndexNamePrefix, middle, suffix)
  320. }
  321. }
  322. maxCols := 5 // 每行只读取前5列即可
  323. startDateRow := 0 // 数据日期起始行(第一行), 后面依次加4行读取
  324. startDataRow := 2 // 数据值起始行(第三行), 后面依次加4行读取
  325. sumDateRow := 0 // 数据日期累加的行, 每加4次重置0
  326. sumDataRow := 0 // 数据值累加的行, 每加4次重置0
  327. currDate := "" // 最近的一次日期
  328. stop := false // 结束读取excel
  329. xlsFile, e := xls.OpenFile(filePath)
  330. if e != nil {
  331. err = fmt.Errorf("open xls file err: %s", e.Error())
  332. return
  333. }
  334. sheet, e := xlsFile.GetSheet(0)
  335. if e != nil {
  336. err = fmt.Errorf("GetSheet err: %s", e.Error())
  337. return
  338. }
  339. rows := sheet.GetRows()
  340. for i, row := range rows {
  341. sumDateRow += 1
  342. sumDataRow += 1
  343. // 第一个日期行/后续每4行取一次日期
  344. if i == startDateRow || sumDateRow == 4 {
  345. if stop {
  346. break
  347. }
  348. sumDateRow = 0
  349. for k, cell := range row.GetCols() {
  350. // 日期只取第一个单元格中的
  351. if k > 0 {
  352. break
  353. }
  354. strDates := strings.TrimSpace(cell.GetString())
  355. strDates = strings.ReplaceAll(strDates, "样本焦企炼焦煤库存", "")
  356. strDates = strings.ReplaceAll(strDates, "\x00", "")
  357. strDates = strings.ReplaceAll(strDates, "本焦企炼焦煤库存", "")
  358. strDateArr := strings.Split(strDates, "-")
  359. // 正常情况下, 长度不为2说明读取到了最后一行了
  360. if len(strDateArr) != 2 {
  361. utils.FileLog.Info(fmt.Sprintf("第%d行数据日期长度有误, 结束读取", i+1))
  362. stop = true
  363. break
  364. }
  365. t, e := time.Parse("2006.1.2", strDateArr[1])
  366. if e != nil {
  367. utils.FileLog.Info(fmt.Sprintf("第%d行数据日期有误, err: %s", i+1, e.Error()))
  368. break
  369. }
  370. currDate = t.Format(utils.FormatDate)
  371. }
  372. }
  373. // 第一个数据行/后续每4行取一次数据
  374. if i == startDataRow || sumDataRow == 4 {
  375. if currDate == "" {
  376. utils.FileLog.Info(fmt.Sprintf("第%d行数据对应日期有误", i+1))
  377. continue
  378. }
  379. sumDataRow = 0
  380. for k, cell := range row.GetCols() {
  381. if k >= maxCols {
  382. break
  383. }
  384. if k == 0 {
  385. continue
  386. }
  387. val := cell.GetFloat64()
  388. indexColIndex[k].ExcelDataMap[currDate] = fmt.Sprint(val)
  389. }
  390. // 重置日期
  391. currDate = ""
  392. }
  393. }
  394. indexes = make([]*models.FenWeiExcelIndex, 0)
  395. for _, v := range indexColIndex {
  396. if v.IndexCode == "" {
  397. continue
  398. }
  399. indexes = append(indexes, v)
  400. }
  401. return
  402. }
  403. // GetFenWeiClassify 获取汾渭数据分类
  404. func GetFenWeiClassify() (classifies []models.BaseFromFenWeiClassifyItem, err error) {
  405. params := make(map[string]interface{})
  406. result, e := PostEdbLib(params, utils.LIB_ROUTE_FENWEI_CLASSIFY)
  407. if e != nil {
  408. b, _ := json.Marshal(params)
  409. err = fmt.Errorf("GetFenWeiClassify, PostEdbLib err: %s, params: %s", e.Error(), string(b))
  410. return
  411. }
  412. resp := new(models.EdbLibFenWeiClassifyResponse)
  413. if e = json.Unmarshal(result, &resp); e != nil {
  414. err = fmt.Errorf(fmt.Sprintf("GetFenWeiClassify, json.Unmarshal err: %s", e.Error()))
  415. return
  416. }
  417. if resp.Ret != 200 {
  418. err = fmt.Errorf(fmt.Sprintf("GetFenWeiClassify, Msg: %s, ErrMsg: %s", resp.Msg, resp.ErrMsg))
  419. return
  420. }
  421. classifies = resp.Data
  422. return
  423. }
  424. // AnalysisFenWeiNewExcel 解析汾渭增量Excel数据
  425. func AnalysisFenWeiNewExcel(filePath string) (err error) {
  426. defer func() {
  427. if err != nil {
  428. fmt.Printf("AnalysisFenWeiNewExcel ErrMsg: %s\n", err.Error())
  429. utils.FileLog.Info(fmt.Sprintf("AnalysisFenWeiNewExcel ErrMsg: %s", err.Error()))
  430. }
  431. }()
  432. fileName := path.Base(filePath)
  433. var indexes []*models.FenWeiExcelIndex
  434. var e error
  435. if strings.Contains(fileName, FenWeiExcelHistoryNameA) {
  436. indexes, e = AnalysisFenWeiNewExcelNormal(filePath, FenWeiExcelHistoryNameA)
  437. } else if strings.Contains(fileName, FenWeiExcelHistoryNameB) {
  438. indexes, e = AnalysisFenWeiNewExcelNormal(filePath, FenWeiExcelHistoryNameB)
  439. } else if strings.Contains(fileName, FenWeiExcelHistoryNameC) {
  440. indexes, e = AnalysisFenWeiNewExcelNormal(filePath, FenWeiExcelHistoryNameC)
  441. } else if strings.Contains(fileName, FenWeiExcelHistoryNameD) {
  442. indexes, e = AnalysisFenWeiNewExcelNormal(filePath, FenWeiExcelHistoryNameD)
  443. } else if strings.Contains(fileName, FenWeiExcelHistoryNameE) {
  444. indexes, e = AnalysisFenWeiExcelYangBen(filePath) // 样本焦化厂-增量数据和历史数据excel格式相同
  445. } else {
  446. utils.FileLog.Info(fmt.Sprintf("文件名有误, FileName: %s", fileName))
  447. return
  448. }
  449. if e != nil {
  450. utils.FileLog.Info(fmt.Sprintf("获取excel数据失败, FileName: %s, Err: %s", fileName, e))
  451. return
  452. }
  453. if len(indexes) == 0 {
  454. utils.FileLog.Info(fmt.Sprintf("fileName: %s, index empty", fileName))
  455. return
  456. }
  457. // 写入数据
  458. params := make(map[string]interface{})
  459. params["List"] = indexes
  460. params["TerminalCode"] = utils.FenweiTerminalCode
  461. result, e := PostEdbLib(params, utils.LIB_ROUTE_FENWEI_HANDLE)
  462. if e != nil {
  463. b, _ := json.Marshal(params)
  464. utils.FileLog.Info(fmt.Sprintf("fileName: %s, PostEdbLib err: %s, params: %s", fileName, e.Error(), string(b)))
  465. return
  466. }
  467. resp := new(models.BaseEdbLibResponse)
  468. if e := json.Unmarshal(result, &resp); e != nil {
  469. utils.FileLog.Info(fmt.Sprintf("fileName: %s, json.Unmarshal err: %s", fileName, e.Error()))
  470. return
  471. }
  472. if resp.Ret != 200 {
  473. utils.FileLog.Info(fmt.Sprintf("fileName: %s, Msg: %s, ErrMsg: %s", fileName, resp.Msg, resp.ErrMsg))
  474. return
  475. }
  476. return
  477. }
  478. // TODO:AnalysisFenWeiNewExcelNormal 增量数据-动力煤/焦煤产
  479. func AnalysisFenWeiNewExcelNormal(filePath, excelName string) (indexes []*models.FenWeiExcelIndex, err error) {
  480. defer func() {
  481. if err != nil {
  482. fmt.Printf("AnalysisFenWeiNewExcelNormal ErrMsg: %s\n", err.Error())
  483. utils.FileLog.Info(fmt.Sprintf("AnalysisFenWeiNewExcelNormal ErrMsg: %s", err.Error()))
  484. }
  485. }()
  486. return
  487. }