package services
import (
"baliance.com/gooxml/color"
"baliance.com/gooxml/document"
"baliance.com/gooxml/measurement"
"baliance.com/gooxml/schema/soo/ofc/sharedTypes"
"baliance.com/gooxml/schema/soo/wml"
"bytes"
"encoding/json"
"errors"
"fmt"
wkhtml "github.com/SebastiaanKlippert/go-wkhtmltopdf"
"github.com/shopspring/decimal"
"hongze/hz_crm_api/models/contract"
"hongze/hz_crm_api/models/contract/request"
"hongze/hz_crm_api/utils"
"html/template"
"os"
"os/exec"
"path"
"reflect"
"strconv"
"strings"
"time"
)
type TableData struct {
List []TableRow `json:"table" description:"列数据"`
}
type TableRow struct {
RowList []TableCel `json:"row" description:"列数据"`
}
type TableCel struct {
Value string `json:"value" description:"展示的数据"`
ColumnSpan int `json:"column_span" description:"需要合同的列数量"`
RowSpan int `json:"row_span" description:"需要合同的行数量"`
IsMerged bool `json:"is_merged" description:"是否需要上下行合并"`
IsFirstMerged bool `json:"is_first_merged" description:"是否是第一次合并上下行"`
Background string `json:"background" description:"背景色"`
IsBold bool `json:"is_bold" description:"是否加粗显示"`
TextAlign string `json:"text_align" description:"对齐方式"`
FontSize float64 `json:"font_size" description:"字体大小"`
WidthPercent float64 `json:"width_percent" description:"单元格宽度占整个表格的百分比"`
}
// 获取颜色配置
func getColorConf(background string) (foreground color.Color) {
switch background {
case "slate_gray": //石板灰
foreground = color.SlateGray
case "light_slate_gray": //浅石板灰
foreground = color.LightSlateGray
case "light_gray": //浅灰
foreground = color.LightGray
case "gray": //灰色
foreground = color.Gray
case "gray_1": //灰色_1(中浅灰)
foreground = color.RGB(uint8(215), uint8(215), uint8(215))
case "gray_2": //灰色_2(浅灰)
foreground = color.RGB(uint8(241), uint8(241), uint8(241))
case "dim_gray": //暗灰色
foreground = color.DimGray
case "dark_slate_gray": //深灰色
foreground = color.DarkSlateGray
default:
foreground = color.LightGray
}
return
}
func getTextAlignConf(textAlign string) (align wml.ST_Jc) {
switch textAlign {
case "left": //居左
align = wml.ST_JcLeft
case "center": //居中
align = wml.ST_JcCenter
case "right": //居右
align = wml.ST_JcRight
case "both": //
align = wml.ST_JcBoth
default:
align = wml.ST_JcLeft
}
return
}
// GenerateWord 生成word
func GenerateWord(contractDetail *contract.ContractDetail) (err error) {
wordTemplatePath := getWordPath(contractDetail.TemplateId)
if wordTemplatePath == "" {
err = errors.New("找不到对应的合同模板")
return
}
doc, err := document.Open(wordTemplatePath)
if err != nil {
fmt.Println("error opening document: %s", err)
return
}
paragraphs := []document.Paragraph{}
for _, p := range doc.Paragraphs() {
paragraphs = append(paragraphs, p)
}
// This sample document uses structured document tags, which are not common
// except for in document templates. Normally you can just iterate over the
// document's paragraphs.
for _, sdt := range doc.StructuredDocumentTags() {
for _, p := range sdt.Paragraphs() {
paragraphs = append(paragraphs, p)
}
}
doc.AddParagraph()
for _, p := range paragraphs {
for _, r := range p.Runs() {
switch r.Text() {
case "{{address}}":
// ClearContent clears both text and line breaks within a run,
// so we need to add the line break back
r.ClearContent()
address := getContractAddress(contractDetail)
r.AddText(address)
//r.AddBreak()
//para := doc.InsertParagraphBefore(p)
//para.AddRun().AddText("Mr.")
//para.SetStyle("Name") // Name is a default style in this template file
//
//para = doc.InsertParagraphAfter(p)
//para.AddRun().AddText("III")
//para.SetStyle("Name")
case "{{postcode}}":
r.ClearContent()
r.AddText(contractDetail.Postcode)
case "{{phone}}":
r.ClearContent()
r.AddText(contractDetail.Phone)
case "{{fax}}":
r.ClearContent()
r.AddText(contractDetail.Fax)
case "{{remark}}":
r.ClearContent()
remark := contractDetail.Remark
if remark == "" {
remark = "无"
}
r.AddText(remark)
case "{{start_date}}":
r.ClearContent()
r.AddText(contractDetail.StartDate.Format("2006 年 01 月 02 日"))
case "{{end_date}}":
r.ClearContent()
r.AddText(contractDetail.EndDate.Format("2006 年 01 月 02 日"))
case "{{num_year}}":
r.ClearContent()
//合同结束日期与合同开始日期的时间差(小时差)
newDecimal := decimal.NewFromFloat(contractDetail.EndDate.Sub(contractDetail.StartDate).Hours())
//分母为365天 * 24 小时
newDecimal2 := decimal.NewFromInt(24 * 365)
//计算出来相差多少年,保留一位小数(四舍五入)
numYearDecimal := newDecimal.Div(newDecimal2).Round(1)
//定义最小年份差,不能小于0.1年
minDecimal := decimal.NewFromFloat(0.1)
//如果计算出来的年份差小于0.1年,那么该年份差就赋值 0.1年
if numYearDecimal.LessThan(minDecimal) {
numYearDecimal = minDecimal
}
//cnYear, cnErr := utils.ConvertNumToCn(numYearDecimal.String())
//if cnErr != nil {
// err = cnErr
// return
//}
r.AddText(numYearDecimal.String())
case "{{price}}":
r.ClearContent()
priceStr := ""
//originalPrice := strconv.FormatFloat(contractDetail.OriginalPrice, 'E', -1, 64)
//优惠前金额(小写)
//newDecimal := decimal.NewFromFloat(contractDetail.OriginalPrice)
originalPrice := utils.FormatPrice(contractDetail.OriginalPrice)
priceStr += "小写:" + originalPrice + ","
//优惠前金额(大写)
originalCnyPrice, cnyErr := utils.ConvertNumToCny(contractDetail.OriginalPrice)
if cnyErr != nil {
err = cnyErr
return
}
priceStr += "大写:" + originalCnyPrice
//如果实际支付金额与订单原金额不符
if contractDetail.OriginalPrice != contractDetail.Price {
//优惠后的金额(小写)
//newDecimal := decimal.NewFromFloat(contractDetail.Price)
price := utils.FormatPrice(contractDetail.Price)
priceStr += ",经甲乙双方友好协商,优惠至:" + price + "元,"
//优惠后的金额(大写)
cnyPrice, cnyErr := utils.ConvertNumToCny(contractDetail.Price)
if cnyErr != nil {
err = cnyErr
return
}
priceStr += "大写:" + cnyPrice
}
r.AddText(priceStr)
case "{{pay_remark}}":
r.ClearContent()
r.AddText(contractDetail.PayRemark)
case "{{company_name}}":
r.ClearContent()
r.AddText(contractDetail.CompanyName)
//r.AddBreak()
case "{{services}}":
r.ClearContent()
//赋值当前段落
nowParagraph := p
for i := len(contractDetail.Service) - 1; i >= 0; i-- {
//表格数据
var tableDataList TableData
//表头备注信息
tableTitle := ""
item := contractDetail.Service[i]
//表格数据
if item.HasDetail == "是" && len(item.DetailList) > 0 {
//表格每行数据切片
tableRowList := make([]TableRow, 0)
//遍历获取table行数据
for j := 0; j < len(item.DetailList); j++ {
//列数据样式初始化
isBold := false
backgrandColor := ""
fontSize := 10.0
//表头数据样式
if j == 0 {
isBold = true
backgrandColor = "gray_2"
fontSize = 12.0
}
//获取每一列的数据
tmpCellList, colErr := getColList(item.DetailList[j])
if colErr != nil {
err = colErr
return
}
//定义生成table列数据切片
tableCelList := make([]TableCel, 0)
lenCell := len(tmpCellList)
for k := 0; k < len(tmpCellList); k++ {
//计算出来每一列的宽度占比 start
//总宽度
newDecimal := decimal.NewFromFloat(100)
//总列数
newDecimal2 := decimal.NewFromInt(int64(lenCell))
//计算出来每一列的宽度占比(四舍五入)
widthPercent, _ := newDecimal.Div(newDecimal2).Round(3).Float64()
//if !ok {
// err = errors.New("word普通数据表格宽度百分比计算失败")
// return
//}
//计算出来每一列的宽度占比 end
tableCel := TableCel{
Value: tmpCellList[k],
TextAlign: "center",
//ColumnSpan int `json:"column_span";description:"需要合同的列数量"`
//IsMerged bool `json:"is_merged";description:"是否需要上下行合并"`
Background: backgrandColor,
IsBold: isBold,
FontSize: fontSize,
WidthPercent: widthPercent,
}
tableCelList = append(tableCelList, tableCel)
}
//将每行数据插入到table行数据切片之中
tableRow := TableRow{
RowList: tableCelList,
}
tableRowList = append(tableRowList, tableRow)
}
//赋值table表格数据
tableDataList.List = tableRowList
tableTitle = "依照《弘则研究FICC客户服务列表2022》中 小套餐 的服务内容,详细如下:"
} else {
//获取预设的表格数据
contractServiceTemplate, tmpErr := contract.GetContractServiceTemplateById(item.ServiceTemplateId)
if tmpErr != nil {
err = tmpErr
return
}
//赋值table表格数据
jsonStr := contractServiceTemplate.TableValue
err = json.Unmarshal([]byte(jsonStr), &tableDataList)
if err != nil {
return
}
//表头备注信息
tableTitle = contractServiceTemplate.Remark
}
//往word中添加表格数据
tmpParagraph, tmpErr := addTable(tableTitle, tableDataList, doc, nowParagraph)
if tmpErr != nil {
err = tmpErr
return
}
//fmt.Println("nowParagraph:", nowParagraph, "tmpParagraph:", tmpParagraph)
//fmt.Println("doc:", doc.Paragraphs())
//fmt.Println("==========:")
nowParagraph = tmpParagraph
}
default:
//fmt.Println("not modifying", r.Text())
}
}
}
doc.SaveToFile(fmt.Sprint("./static/word/系统生成合同", contractDetail.ContractId, ".docx"))
return
}
// 添加表格数据
func addTable(title string, tableDataList TableData, doc *document.Document, paragraph document.Paragraph) (nowParagraph document.Paragraph, err error) {
//fmt.Println("表头名称:", title)
//插入一个新的段落
nowParagraph = doc.InsertParagraphBefore(paragraph)
nowRun := nowParagraph.AddRun()
nowRun.AddBreak()
//if title != "" {
// fmt.Println("表头名称:", title)
// nowRun.Properties().SetSize(11)
// nowRun.Properties().SetBold(true)
// nowRun.AddText(title)
// nowRun.AddBreak()
//}
//再次插入一个新段落
//_ = doc.InsertParagraphAfter(nowParagraph)
//表格数据
{
table := doc.InsertTableAfter(nowParagraph)
//设置表格宽度
table.Properties().SetWidth(6.5 * measurement.Inch)
//表格宽度设置为自动
//table.Properties().SetWidthAuto()
//边框
borders := table.Properties().Borders()
// thin borders
borders.SetAll(wml.ST_BorderSingle, color.Auto, measurement.Zero)
//表格数据
rowList := tableDataList.List
//每一列合并单元格状态map
rowIsMeged := make(map[int]bool)
//table.Properties().W
for i := 0; i < len(rowList); i++ {
//创建新的一行
row := table.AddRow()
//设置行高,第二个参数是设置固定值还是自动
row.Properties().SetHeight(30*measurement.Point, wml.ST_HeightRuleAtLeast)
//遍历列数据
rowDataList := rowList[i].RowList
if rowDataList != nil {
for j := 0; j < len(rowDataList); j++ {
//当前列是否合并
var isMeged bool
isMeged, ok := rowIsMeged[j]
if !ok {
rowIsMeged[j] = false
isMeged = false
}
cell := row.AddCell()
cellPara := cell.AddParagraph()
run := cellPara.AddRun()
//列数据
cellData := rowDataList[j]
//如果合并列大于0,那么就合并列
if cellData.ColumnSpan > 0 {
// column span / merged cells
cell.Properties().SetColumnSpan(cellData.ColumnSpan)
//_ = row.AddCell()
}
//如果指定了上下单元格合并,那么去合并上下单元格
if cellData.IsMerged {
//将当前合并单元格状态调整为true
rowIsMeged[j] = true
//合并单元格类型
var mergeVal wml.ST_Merge
if isMeged { //如果上一层已经是合并了,那么这一层是继续合并
mergeVal = wml.ST_MergeContinue
} else { //如果上一层不是合并,那么这一层是开始合并
mergeVal = wml.ST_MergeRestart
}
cell.Properties().SetVerticalMerge(mergeVal)
} else {
//将当前合并单元格状态调整为false,这样后续如果再次碰到合并单元格操作,就是重新开始合并了
rowIsMeged[j] = false
}
//背景色
if cellData.Background != "" {
cell.Properties().SetShading(wml.ST_ShdSolid, getColorConf(cellData.Background), color.Auto)
}
//填充内容(文字)垂直对齐方式
cell.Properties().SetVerticalAlignment(wml.ST_VerticalJcCenter)
//将单元格设置为宽度百分比
if cellData.WidthPercent > 0 {
cell.Properties().SetWidthPercent(cellData.WidthPercent)
}
//文字排版(居中、左、右)
if cellData.TextAlign != "" {
cellPara.Properties().SetAlignment(getTextAlignConf(cellData.TextAlign))
//cellPara.Properties().SetAlignment(wml.ST_JcLeft)
}
//cell.Properties().SetAli
//设置是否加粗
run.Properties().SetBold(cellData.IsBold)
//设置字体大小
fontSize := 10.0
if cellData.FontSize > 0 {
fontSize = cellData.FontSize
}
run.Properties().SetSize(measurement.Distance(fontSize * measurement.Point))
//设置段落间的间距
cellPara.Properties().Spacing().SetLineSpacing(measurement.Distance(1.4*fontSize*measurement.Point), wml.ST_LineSpacingRuleAuto)
//设置段前间距
cellPara.Properties().Spacing().SetBefore(measurement.Distance(0.9 * fontSize * measurement.Point))
//设置段后间距
cellPara.Properties().Spacing().SetAfter(measurement.Distance(0.5 * fontSize * measurement.Point))
//设置字体
run.Properties().SetFontFamily("宋体")
//设置排序
run.Properties().SetVerticalAlignment(sharedTypes.ST_VerticalAlignRunBaseline)
//设置显示的文字
if cellData.Value != "" {
strSlice := strings.Split(cellData.Value, "
")
for s := 0; s < len(strSlice); s++ {
if s > 0 {
run.AddBreak()
}
run.AddText(strSlice[s])
}
} else {
run.AddText("")
}
}
}
}
}
return
}
// 获取生成word的docx模板文件
func getWordPath(templateId int) string {
var path string
switch templateId {
case 1:
path = "./static/word/template_1.docx"
case 2:
path = "./static/word/template_2.docx"
}
return path
}
// html转pdf数据样式
type html2pdfData struct {
CompanyName string `description:"甲方名称"`
ContractCode string `description:"合同编号"`
Address string `description:"甲方地址"`
PostcodeDisplay string `description:"甲方邮编;是否展示"`
Postcode string `description:"甲方邮编"`
PhoneDisplay string `description:"甲方电话;是否展示"`
Phone string `description:"甲方电话"`
FaxDisplay string `description:"传真;是否展示"`
Fax string `description:"传真"`
RemarkDisplay string `description:"备注;是否展示"`
Remark string `description:"备注"`
PayRemark string `description:"支付备注"`
StartDate string `description:"合同开始日期"`
EndDate string `description:"合同结束日期"`
NumYear string `description:"合同有效期"`
Price string `description:"支付金额"`
TableHtml string `description:"表格数据"`
}
// GetHtmlByContractDetail 获取合同样式预览的html
func GetHtmlByContractDetail(contractDetail *contract.ContractDetail, htmlType string) (contractHtml string, err error) {
tmpContractDetail := *contractDetail
contractTemplate, err := contract.GetContractTemplateByTemplateId(tmpContractDetail.TemplateId)
if err != nil {
return
}
// 初始化合同中一些特定区域的文字展示配置
contentConfigMap := make(map[string]string)
err = json.Unmarshal([]byte(contractTemplate.ContentConfig), &contentConfigMap)
if err != nil {
return
}
htmlTpl := contractTemplate.Html
if htmlType == "pdf" {
htmlTpl = contractTemplate.PdfHtml
}
myTpl := template.Must(template.New("contract").Parse(htmlTpl))
//合同有效期
contractServiceAndDetailList := make([]*contract.ContractServiceAndDetail, 0) //服务内容
if tmpContractDetail.ContractBusinessType == "代付合同" {
if tmpContractDetail.RelationContractDetailList != nil && len(tmpContractDetail.RelationContractDetailList) > 0 {
tmpContractDetail.StartDate = tmpContractDetail.RelationContractDetailList[0].StartDate
tmpContractDetail.EndDate = tmpContractDetail.RelationContractDetailList[0].EndDate
contractServiceAndDetailList = tmpContractDetail.RelationContractDetailList[0].Service
}
} else {
contractServiceAndDetailList = tmpContractDetail.Service
}
//地址
address := getContractAddress(&tmpContractDetail)
data := html2pdfData{
CompanyName: tmpContractDetail.CompanyName,
ContractCode: tmpContractDetail.ContractCode,
Address: address,
PostcodeDisplay: "block",
Postcode: tmpContractDetail.Postcode,
PhoneDisplay: "block",
Phone: tmpContractDetail.Phone,
FaxDisplay: "block",
Fax: tmpContractDetail.Fax,
RemarkDisplay: "block",
Remark: tmpContractDetail.Remark,
PayRemark: tmpContractDetail.PayRemark,
StartDate: tmpContractDetail.StartDate.Format("2006年01月02日"),
EndDate: tmpContractDetail.EndDate.Format("2006年01月02日"),
}
if data.Postcode == "" {
data.Postcode = "无"
data.PostcodeDisplay = "none"
}
if data.Fax == "" {
data.Fax = "无"
data.FaxDisplay = "none"
}
if data.Phone == "" {
data.Phone = "无"
data.PhoneDisplay = "none"
}
if data.PayRemark == "" {
data.PayRemark = "无"
}
if data.Remark == "" {
data.Remark = "无"
data.RemarkDisplay = "none"
}
//合同有效期
{
////合同结束日期与合同开始日期的时间差(小时差)
//newDecimal := decimal.NewFromFloat(tmpContractDetail.EndDate.Sub(tmpContractDetail.StartDate).Hours())
////分母为365天 * 24 小时
//newDecimal2 := decimal.NewFromInt(24 * 365)
////计算出来相差多少年,保留一位小数(四舍五入)
//numYearDecimal := newDecimal.Div(newDecimal2).Round(1)
////定义最小年份差,不能小于0.1年
//minDecimal := decimal.NewFromFloat(0.1)
////如果计算出来的年份差小于0.1年,那么该年份差就赋值 0.1年
//if numYearDecimal.LessThan(minDecimal) {
// numYearDecimal = minDecimal
//}
//
////合同有效期
//data.NumYear = numYearDecimal.String()
tmpPrintContent, tmpErr := utils.CalculationDate(tmpContractDetail.StartDate, tmpContractDetail.EndDate)
if tmpErr != nil {
err = tmpErr
return
}
data.NumYear = tmpPrintContent
}
//合同金额
{
priceStr := ""
//originalPrice := strconv.FormatFloat(tmpContractDetail.OriginalPrice, 'E', -1, 64)
//优惠前金额(小写)
//newDecimal := decimal.NewFromFloat(tmpContractDetail.OriginalPrice)
originalPrice := utils.FormatPrice(tmpContractDetail.OriginalPrice)
priceStr += "小写:" + originalPrice + "元,"
//优惠前金额(大写)
originalCnyPrice, cnyErr := utils.ConvertNumToCny(tmpContractDetail.OriginalPrice)
if cnyErr != nil {
err = cnyErr
return
}
priceStr += "大写:" + originalCnyPrice
//如果实际支付金额与订单原金额不符
if tmpContractDetail.OriginalPrice != tmpContractDetail.Price {
//优惠后的金额(小写)
//newDecimal := decimal.NewFromFloat(tmpContractDetail.Price)
price := utils.FormatPrice(tmpContractDetail.Price)
priceStr += ",经甲乙双方友好协商,优惠至:" + price + "元,"
//优惠后的金额(大写)
cnyPrice, cnyErr := utils.ConvertNumToCny(tmpContractDetail.Price)
if cnyErr != nil {
err = cnyErr
return
}
priceStr += "大写:" + cnyPrice
}
data.Price = priceStr
}
buf := new(bytes.Buffer) //实现了读写方法的可变大小的字节缓冲
tplErr := myTpl.Execute(buf, data)
if tplErr != nil {
err = tplErr
return
}
contractHtml = buf.String()
//服务内容
{
tableStr := ""
tableDataSlice := make([]TableData, 0)
tableTitleSlice := make([]string, 0)
title := ``
if tmpTitle, ok := contentConfigMap["title1"]; ok {
title = tmpTitle
}
for i := 0; i < len(contractServiceAndDetailList); i++ {
//表格数据
var tableDataList TableData
item := contractServiceAndDetailList[i]
//表头备注信息
tableTitleSlice = append(tableTitleSlice, item.Title)
//表格数据
if item.HasDetail == "是" && len(item.DetailList) > 0 {
//表格每行数据切片
tableRowList := make([]TableRow, 0)
//遍历获取table行数据
for j := 0; j < len(item.DetailList); j++ {
//列数据样式初始化
isBold := false
backgrandColor := ""
fontSize := 13.0
//表头数据样式
if j == 0 {
isBold = true
backgrandColor = "gray_2"
fontSize = 13.0
}
//获取每一列的数据
tmpCellList, colErr := getColList(item.DetailList[j])
if colErr != nil {
err = colErr
return
}
//定义生成table列数据切片
tableCelList := make([]TableCel, 0)
lenCell := len(tmpCellList)
for k := 0; k < len(tmpCellList); k++ {
//默认30%的宽度,如果不是第一列,那么需要额外计算
widthPercent := 30.0
if k > 0 {
//计算出来每一列的宽度占比 start
//总宽度
newDecimal := decimal.NewFromFloat(70)
//总列数
newDecimal2 := decimal.NewFromInt(int64(lenCell) - 1)
//计算出来每一列的宽度占比(四舍五入)
tmpWidthPercent, _ := newDecimal.Div(newDecimal2).Round(3).Float64()
//if !ok {
// err = errors.New("word普通数据表格宽度百分比计算失败")
// return
//}
widthPercent = tmpWidthPercent
//计算出来每一列的宽度占比 end
}
tableCel := TableCel{
Value: tmpCellList[k],
TextAlign: "center",
//ColumnSpan int `json:"column_span";description:"需要合同的列数量"`
//IsMerged bool `json:"is_merged";description:"是否需要上下行合并"`
Background: backgrandColor,
IsBold: isBold,
FontSize: fontSize,
WidthPercent: widthPercent,
}
tableCelList = append(tableCelList, tableCel)
}
//将每行数据插入到table行数据切片之中
tableRow := TableRow{
RowList: tableCelList,
}
tableRowList = append(tableRowList, tableRow)
}
//赋值table表格数据
tableDataList.List = tableRowList
} else {
//赋值table表格数据
jsonStr := item.TableValue
tmpEerr := json.Unmarshal([]byte(jsonStr), &tableDataList)
if tmpEerr != nil {
err = tmpEerr
return
}
}
tableDataSlice = append(tableDataSlice, tableDataList)
}
titleStr := strings.Join(tableTitleSlice, "、")
title += titleStr + "的服务内容,详细如下:"
if htmlType == "pdf" {
tableStr += `
` + title + `
` } else { tableStr = `` + title + `
` } for _, tableDataList := range tableDataSlice { //往word中添加表格数据 if htmlType == "pdf" { tableStr += getTableStrByPdf(tableDataList) } else { tableStr += getTableStr(tableDataList) } } data.TableHtml = tableStr } //fmt.Println("TableHtml:", data.TableHtml) contractHtml = strings.Replace(contractHtml, `\{\{\{TableHtml\}\}\}`, data.TableHtml, -1) return //生成pdf //pdfPath := fmt.Sprint("./static/word/系统生成合同", contractDetail.ContractCode, ".pdf") //err = Html2Pdf(contractHtml, pdfPath) //if err != nil { // return //} ////defer func() { //// //删除对应的Pdf //// os.Remove(pdfPath) ////}() // //return } // 生成合同服务的预览表格html代码 func getTableStr(tableDataList TableData) (tableStr string) { //如果表格需要分页,那么在table的style里面添加该配置:page-break-inside: avoid !important tableStr += `2.市场跟踪类报告 | //row := table.AddRow() ////设置行高,第二个参数是设置固定值还是自动 //row.Properties().SetHeight(30*measurement.Point, wml.ST_HeightRuleAtLeast) // //遍历列数据 rowDataList := rowList[i].RowList cellStr := "" if rowDataList != nil { for j := 0; j < len(rowDataList); j++ { //当前列是否合并 //2.市场跟踪类报告 | //市场跟踪 | //市场估值 | tdStr := `0 { // column span / merged cells cellOtherStr += ` colspan="` + strconv.Itoa(cellData.ColumnSpan) + `" ` } //如果指定了上下单元格合并,那么去合并上下单元格 if cellData.IsMerged { if cellData.IsFirstMerged { cellOtherStr += ` rowspan="` + strconv.Itoa(cellData.RowSpan) + `" ` } else { //如果是合并行,且不是第一行,那么就退出当前单元格循环,进入下一个循环 continue } } //背景色 if cellData.Background != "" { styleStr += `background-color: #F0F2F5;` } //将单元格设置为宽度百分比 if cellData.WidthPercent > 0 { widthDecimal := decimal.NewFromFloat(cellData.WidthPercent) cellOtherStr += ` width="` + widthDecimal.String() + `%" ` } //文字排版(居中、左、右) if cellData.TextAlign != "" { cellOtherStr += ` align="` + cellData.TextAlign + `" ` } //cell.Properties().SetAli //设置是否加粗 if cellData.IsBold { styleStr += `font-weight:bold;` } //设置字体大小 fontSize := 10.0 if cellData.FontSize > 0 { fontSize = cellData.FontSize } fontDecimal := decimal.NewFromFloat(fontSize) styleStr += `font-size: ` + fontDecimal.String() + `pt;` bodyStr := cellData.Value styleStr += `" ` cellStr += tdStr + styleStr + cellOtherStr + `>` + bodyStr + ` | ` } } tableStr += cellStr + `
2.市场跟踪类报告 | //row := table.AddRow() ////设置行高,第二个参数是设置固定值还是自动 //row.Properties().SetHeight(30*measurement.Point, wml.ST_HeightRuleAtLeast) // //遍历列数据 rowDataList := rowList[i].RowList cellStr := "" if rowDataList != nil { for j := 0; j < len(rowDataList); j++ { //当前列是否合并 //2.市场跟踪类报告 | //市场跟踪 | //市场估值 | tdStr := `0 { // column span / merged cells cellOtherStr += ` colspan="` + strconv.Itoa(cellData.ColumnSpan) + `" ` } //如果指定了上下单元格合并,那么去合并上下单元格 if cellData.IsMerged { if cellData.IsFirstMerged { cellOtherStr += ` rowspan="` + strconv.Itoa(cellData.RowSpan) + `" ` } else { //如果是合并行,且不是第一行,那么就退出当前单元格循环,进入下一个循环 continue } } //背景色 if cellData.Background != "" { styleStr += `background-color: #F0F2F5;` } //将单元格设置为宽度百分比 if cellData.WidthPercent > 0 { widthDecimal := decimal.NewFromFloat(cellData.WidthPercent) cellOtherStr += ` width="` + widthDecimal.String() + `%" ` } //文字排版(居中、左、右) if cellData.TextAlign != "" { cellOtherStr += ` align="` + cellData.TextAlign + `" ` } //cell.Properties().SetAli //设置是否加粗 if cellData.IsBold { styleStr += `font-weight:bold;` } //设置字体大小 fontSize := 10.0 if cellData.FontSize > 0 { fontSize = cellData.FontSize } fontDecimal := decimal.NewFromFloat(fontSize) styleStr += `font-size: ` + fontDecimal.String() + `pt;` bodyStr := cellData.Value styleStr += `" ` cellStr += tdStr + styleStr + cellOtherStr + `>` + bodyStr + ` | ` } } tableStr += cellStr + `