report-product-excel.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. package api
  2. import (
  3. "box-cost/db/model"
  4. "fmt"
  5. "math"
  6. "regexp"
  7. _ "image/gif"
  8. _ "image/jpeg"
  9. _ "image/png"
  10. "github.com/xuri/excelize/v2"
  11. )
  12. type ReportProductExcel struct {
  13. Offset int
  14. Row int
  15. Title string //标题
  16. Excel *excelize.File
  17. SheetName string
  18. AlignCenterStyle int
  19. Content *model.ProductBill
  20. BudgetAmount float64
  21. RealAmount float64
  22. }
  23. func (b *ReportProductExcel) drawTitle() error {
  24. b.Row++
  25. startCell := fmt.Sprintf("A%d", b.Row)
  26. err := b.Excel.MergeCell(b.SheetName, startCell, fmt.Sprintf("J%d", b.Row))
  27. if err != nil {
  28. return err
  29. }
  30. style, err := b.Excel.NewStyle(&excelize.Style{
  31. Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"},
  32. Font: &excelize.Font{Bold: true, Size: 18}})
  33. if err != nil {
  34. return err
  35. }
  36. err = b.Excel.SetCellStyle(b.SheetName, startCell, startCell, style)
  37. if err != nil {
  38. return err
  39. }
  40. b.Excel.SetRowHeight(b.SheetName, b.Row, 23)
  41. b.Excel.SetCellValue(b.SheetName, startCell, b.Title)
  42. return nil
  43. }
  44. func (b *ReportProductExcel) drawSubTitles() error {
  45. b.Row++
  46. styleLeft, err := b.Excel.NewStyle(&excelize.Style{
  47. Alignment: &excelize.Alignment{Horizontal: "left", Vertical: "center"},
  48. Font: &excelize.Font{Size: 11}})
  49. if err != nil {
  50. return err
  51. }
  52. styleRight, err := b.Excel.NewStyle(&excelize.Style{
  53. Alignment: &excelize.Alignment{Horizontal: "right", Vertical: "center"},
  54. Font: &excelize.Font{Size: 11}})
  55. if err != nil {
  56. return err
  57. }
  58. var drawLeft = func(rowIndex int, value string) error {
  59. //左边1
  60. left1Cell := fmt.Sprintf("A%d", rowIndex)
  61. err = b.Excel.MergeCell(b.SheetName, left1Cell, fmt.Sprintf("F%d", rowIndex))
  62. if err != nil {
  63. return err
  64. }
  65. err = b.Excel.SetCellStyle(b.SheetName, left1Cell, left1Cell, styleLeft)
  66. if err != nil {
  67. return err
  68. }
  69. b.Excel.SetCellValue(b.SheetName, left1Cell, value)
  70. return nil
  71. }
  72. var drawRight = func(rowIndex int, value string) error {
  73. right1Cell := fmt.Sprintf("G%d", rowIndex)
  74. err = b.Excel.MergeCell(b.SheetName, right1Cell, fmt.Sprintf("J%d", rowIndex))
  75. if err != nil {
  76. return err
  77. }
  78. err = b.Excel.SetCellStyle(b.SheetName, right1Cell, right1Cell, styleRight)
  79. if err != nil {
  80. return err
  81. }
  82. b.Excel.SetCellValue(b.SheetName, right1Cell, value)
  83. return nil
  84. }
  85. //第一行
  86. drawLeft(b.Row, "需求方(甲方):"+b.Title+"订单")
  87. drawRight(b.Row, "单号:"+b.Content.SerialNumber)
  88. b.Excel.SetRowHeight(b.SheetName, b.Row, 21)
  89. //第二行
  90. drawLeft(b.Row+1, "供应方(乙方):"+b.Content.Supplier)
  91. timeformat := b.Content.CreateTime.Local().Format("2006年01月02号 15:04:05")
  92. drawRight(b.Row+1, "下单时间:"+timeformat)
  93. b.Excel.SetRowHeight(b.SheetName, b.Row+1, 21)
  94. //第三行
  95. drawLeft(b.Row+2, "产品名称:"+b.Content.ProductName)
  96. status := ""
  97. if b.Content.Status == "complete" {
  98. status = "已完成"
  99. }
  100. if b.Content.Status == "created" {
  101. status = "进行中"
  102. }
  103. drawRight(b.Row+2, "状态:"+status)
  104. b.Excel.SetRowHeight(b.SheetName, b.Row+2, 21)
  105. return nil
  106. }
  107. func (b *ReportProductExcel) drawTableTitle() error {
  108. b.Row++
  109. // 品名 规格 数量 单位 单价 金额
  110. var drawCol = func(prefix string, value string) error {
  111. left1Cell := fmt.Sprintf("%s%d", prefix, b.Row)
  112. left2Cell := fmt.Sprintf("%s%d", prefix, b.Row+1)
  113. err := b.Excel.MergeCell(b.SheetName, left1Cell, left2Cell)
  114. if err != nil {
  115. return err
  116. }
  117. err = b.Excel.SetCellStyle(b.SheetName, left1Cell, left2Cell, b.AlignCenterStyle)
  118. if err != nil {
  119. return err
  120. }
  121. return b.Excel.SetCellValue(b.SheetName, left1Cell, value)
  122. }
  123. // a采购项目 b规格 c下单数量 d单位 e完成数量 f单价 g预算金额 h实际金额 i交货时间 j备注
  124. drawCol("A", "采购项目")
  125. drawCol("B", "规格")
  126. drawCol("C", "下单数量")
  127. drawCol("D", "单位")
  128. drawCol("E", "完成数量")
  129. drawCol("F", "单价")
  130. drawCol("G", "预算金额")
  131. drawCol("H", "实际金额")
  132. drawCol("I", "交货时间")
  133. drawCol("J", "备注")
  134. return nil
  135. }
  136. func (b *ReportProductExcel) drawTableContent() error {
  137. b.Row += 2
  138. var DrawRow = func(rowIndex int, values ...string) {
  139. charas := []string{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J"}
  140. for i, c := range charas {
  141. v := ""
  142. if i < len(values) {
  143. v = values[i]
  144. }
  145. b.Excel.SetCellValue(b.SheetName, fmt.Sprintf("%s%d", c, rowIndex), v)
  146. val2Cel := fmt.Sprintf("%s%d", c, rowIndex)
  147. b.Excel.SetCellStyle(b.SheetName, val2Cel, val2Cel, b.AlignCenterStyle)
  148. var magN float64 = 1
  149. lenv := len([]rune(v))
  150. magN = math.Ceil(float64(lenv) / 10)
  151. b.Excel.SetRowHeight(b.SheetName, rowIndex, 21*magN)
  152. }
  153. }
  154. products := b.Content.Products
  155. if len(products) > 0 {
  156. for _, product := range products {
  157. deliveryTime := product.DeliveryTime.Local().Format("2006-01-02")
  158. realCount := ""
  159. realPrice := ""
  160. // 预算金额
  161. budgetAmount := fmt.Sprintf("%.3f", float64(product.OrderCount)*product.OrderPrice)
  162. b.FormatToEmpty(&budgetAmount)
  163. // 实际完成数
  164. realCount = fmt.Sprintf("%d", product.ConfirmCount)
  165. b.FormatToEmpty(&realCount)
  166. // 实际金额
  167. realPrice = fmt.Sprintf("%.3f", float64(product.ConfirmCount)*product.OrderPrice)
  168. b.FormatToEmpty(&realPrice)
  169. // a采购项目 b规格 c下单数量 d单位 e完成数量 f单价 g预算金额 h实际金额 i交货时间 j备注
  170. orderCount := fmt.Sprintf("%d", product.OrderCount)
  171. price := fmt.Sprintf("%.3f", product.OrderPrice)
  172. b.FormatToEmpty(&price)
  173. DrawRow(b.Row, product.Name, product.Norm, orderCount, product.Unit, realCount, price, budgetAmount, realPrice, deliveryTime, product.Remark)
  174. b.Row++
  175. b.BudgetAmount += float64(product.OrderCount) * product.OrderPrice
  176. b.RealAmount += float64(product.ConfirmCount) * product.OrderPrice
  177. }
  178. }
  179. return nil
  180. }
  181. func (b *ReportProductExcel) drawRemark() error {
  182. // 填备注
  183. b.Row++
  184. remarkTitleCell := fmt.Sprintf("A%d", b.Row)
  185. b.Excel.SetCellValue(b.SheetName, remarkTitleCell, "备注:")
  186. b.Row++
  187. remarkContentScell := fmt.Sprintf("A%d", b.Row)
  188. // 根据换行符确定多少行单元格
  189. reg := regexp.MustCompile(`\n`)
  190. remarkRowNum := len(reg.FindAllString(b.Content.Remark, -1)) + 1
  191. b.Row += remarkRowNum
  192. remarkContentEcell := fmt.Sprintf("J%d", b.Row)
  193. b.Excel.MergeCell(b.SheetName, remarkContentScell, remarkContentEcell)
  194. b.Excel.SetCellValue(b.SheetName, remarkContentScell, b.Content.Remark)
  195. // 签字位置
  196. b.Row += 2
  197. styleLeft, err := b.Excel.NewStyle(&excelize.Style{
  198. Alignment: &excelize.Alignment{Horizontal: "left", Vertical: "center"},
  199. Font: &excelize.Font{Size: 11}})
  200. if err != nil {
  201. return err
  202. }
  203. var drawLeft = func(rowIndex int, value string) error {
  204. //左边1
  205. left1Cell := fmt.Sprintf("A%d", rowIndex)
  206. err := b.Excel.MergeCell(b.SheetName, left1Cell, fmt.Sprintf("E%d", rowIndex))
  207. if err != nil {
  208. return err
  209. }
  210. err = b.Excel.SetCellStyle(b.SheetName, left1Cell, left1Cell, styleLeft)
  211. if err != nil {
  212. return err
  213. }
  214. b.Excel.SetCellValue(b.SheetName, left1Cell, value)
  215. return nil
  216. }
  217. var drawRight = func(rowIndex int, value string) error {
  218. right1Cell := fmt.Sprintf("F%d", rowIndex)
  219. err = b.Excel.MergeCell(b.SheetName, right1Cell, fmt.Sprintf("J%d", rowIndex))
  220. if err != nil {
  221. return err
  222. }
  223. err = b.Excel.SetCellStyle(b.SheetName, right1Cell, right1Cell, styleLeft)
  224. if err != nil {
  225. return err
  226. }
  227. b.Excel.SetCellValue(b.SheetName, right1Cell, value)
  228. return nil
  229. }
  230. //第一行
  231. drawLeft(b.Row, "甲方:"+b.Title)
  232. drawRight(b.Row, "乙方:"+b.Content.Supplier)
  233. b.Excel.SetRowHeight(b.SheetName, b.Row, 21)
  234. //第二行
  235. drawLeft(b.Row+1, "联系人:")
  236. timeformat := b.Content.CreateTime.Local().Format("2006年01月02号 15:04:05")
  237. drawRight(b.Row+1, "联系人:")
  238. b.Excel.SetRowHeight(b.SheetName, b.Row+1, 21)
  239. //第三行
  240. drawLeft(b.Row+2, "时间:"+timeformat)
  241. drawRight(b.Row+2, "时间:"+timeformat)
  242. b.Excel.SetRowHeight(b.SheetName, b.Row+2, 21)
  243. b.Row += 2
  244. return nil
  245. }
  246. func (b *ReportProductExcel) Draws() {
  247. b.drawTitle()
  248. b.drawSubTitles()
  249. b.drawTableTitle()
  250. b.drawTableContent()
  251. b.drawRemark()
  252. }
  253. func NewReportProductBill(f *excelize.File) *ReportProductExcel {
  254. border := []excelize.Border{
  255. {Type: "top", Style: 1, Color: "000000"},
  256. {Type: "left", Style: 1, Color: "000000"},
  257. {Type: "right", Style: 1, Color: "000000"},
  258. {Type: "bottom", Style: 1, Color: "000000"},
  259. }
  260. styleLeft, _ := f.NewStyle(&excelize.Style{
  261. Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"},
  262. Border: border,
  263. Font: &excelize.Font{Size: 10},
  264. })
  265. b := &ReportProductExcel{
  266. Title: "原材料采购单",
  267. SheetName: "Sheet1",
  268. Excel: f,
  269. Offset: 0,
  270. AlignCenterStyle: styleLeft,
  271. }
  272. // f.SetColWidth(b.SheetName, "A", "J", 11.5)
  273. f.SetColWidth(b.SheetName, "A", "A", 17)
  274. f.SetColWidth(b.SheetName, "B", "B", 12)
  275. f.SetColWidth(b.SheetName, "C", "H", 10.5)
  276. f.SetColWidth(b.SheetName, "I", "J", 12)
  277. f.SetPageMargins(b.SheetName, excelize.PageMarginTop(1), excelize.PageMarginLeft(0.25), excelize.PageMarginRight(0))
  278. return b
  279. }
  280. func (b *ReportProductExcel) FormatToEmpty(str *string) {
  281. if *str == "0" || *str == "0.000" {
  282. *str = ""
  283. }
  284. }