123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- package example
- import (
- "encoding/json"
- "fmt"
- "reflect"
- "testing"
- "github.com/tiechui1994/gopdf"
- "github.com/tiechui1994/gopdf/core"
- )
- type Template struct {
- Modelname string `json:"modelname"`
- MultiSelectList []string `json:"multiSelectList"`
- Value interface{} `json:"value"`
- ValueList interface{} `json:"valueList"`
- Modeltype string `json:"modeltype"`
- NeedPrint string `json:"needPrint"`
- TableObj struct {
- Columns []struct {
- ColumnsName string `json:"columnsName"`
- } `json:"columns"` // 列名称
- Rows []string `json:"rows"` // 行名称, 从第2行开算, 第一行是Header,没有
- } `json:"tableObj"`
- TbodyArray [][]struct {
- ColumnsType string `json:"columnsType"` // 当前TableCell类型
- ColumnsName string `json:"columnsName"` // 当前TableCell对应列的名称
- RowName string `json:"rowsName"` // 当前TableCell对于的行名称
- Content interface{} `json:"content"` // 内容
- SelectedOption string `json:"selectedOption"`
- } `json:"tbodyArray"`
- TableTotalArr []interface{} `json:"tableTotalArr"` // 合计
- }
- func handleTable(template Template) (rows, cols int, cells [][]string, hasRowName bool) {
- var (
- colNames = template.TableObj.Columns
- rowNames = template.TableObj.Rows
- body = template.TbodyArray
- )
- hasRowName = len(rowNames) != 0
- cols = len(colNames)
- rows = 1 // 头
- if hasRowName {
- cols += 1 // 第0行
- rows += len(rowNames) // 其余的的行
- } else {
- if isEmpty(body) {
- rows += 1 // 至少有一行
- } else {
- rows += len(body)
- }
- }
- if !isEmpty(template.TableTotalArr) {
- cells = make([][]string, rows+1)
- } else {
- cells = make([][]string, rows)
- }
- for i := range cells {
- cells[i] = make([]string, cols)
- }
- // header
- if hasRowName {
- cells[0][0] = ""
- }
- for i := range colNames {
- if hasRowName {
- cells[0][i+1] = colNames[i].ColumnsName
- } else {
- cells[0][i] = colNames[i].ColumnsName
- }
- }
- // 拥有rowname, 肯定有统计信息
- if hasRowName {
- // body内容: rows - 2 * cols - 1
- for i := 1; i < rows; i++ {
- cells[i][0] = body[i-1][0].RowName
- for j := 0; j < cols-1; j++ {
- if body[i-1][j].ColumnsType == "select" {
- cells[i][j+1] = body[i-1][j].SelectedOption
- continue
- }
- switch body[i-1][j].Content.(type) {
- case string:
- cells[i][j+1] = body[i-1][j].Content.(string)
- case float64:
- cells[i][j+1] = fmt.Sprintf("%0.2f", body[i-1][j].Content)
- }
- }
- }
- // 最后一行
- if !isEmpty(template.TableTotalArr) {
- cells[rows][0] = "合计"
- for j := 0; j < cols-1; j++ {
- switch template.TableTotalArr[j].(type) {
- case string:
- cells[rows][j+1] = template.TableTotalArr[j].(string)
- case float64:
- cells[rows][j+1] = fmt.Sprintf("%.2f", template.TableTotalArr[j].(float64))
- }
- }
- return rows + 1, cols, cells, hasRowName
- }
- return rows, cols, cells, hasRowName
- }
- // 没有rowname, 但是有内容
- if !hasRowName && !isEmpty(body) {
- for i := 1; i < rows; i++ {
- for j := 0; j < cols; j++ {
- if body[i-1][j].ColumnsType == "select" {
- cells[i][j] = body[i-1][j].SelectedOption
- continue
- }
- switch body[i-1][j].Content.(type) {
- case string:
- cells[i][j] = body[i-1][j].Content.(string)
- case float64:
- cells[i][j] = fmt.Sprintf("%0.2f", body[i-1][j].Content.(float64))
- }
- }
- }
- // 合计
- if !isEmpty(template.TableTotalArr) {
- for j := 0; j < cols; j++ {
- switch template.TableTotalArr[j].(type) {
- case string:
- cells[rows][j] = template.TableTotalArr[j].(string)
- case float64:
- cells[rows][j] = fmt.Sprintf("%.2f", template.TableTotalArr[j].(float64))
- }
- }
- return rows + 1, cols, cells, hasRowName
- }
- return rows, cols, cells, hasRowName
- } else {
- for j := 0; j < cols; j++ {
- cells[1][j] = ""
- }
- }
- return rows, cols, cells, hasRowName
- }
- func isEmpty(object interface{}) bool {
- if object == nil {
- return true
- }
- objValue := reflect.ValueOf(object)
- switch objValue.Kind() {
- // collection types are empty when they have no element
- case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
- return objValue.Len() == 0
- case reflect.Ptr:
- if objValue.IsNil() {
- return true
- }
- deref := objValue.Elem().Interface()
- return isEmpty(deref)
- // for all other types, compare against the zero value
- default:
- zero := reflect.Zero(objValue.Type())
- return reflect.DeepEqual(object, zero.Interface())
- }
- }
- func handleTemplateRow(template Template) (isTable bool, key, value string) {
- key = template.Modelname
- switch template.Modeltype {
- case "1", "2", "5", "9":
- if template.Value == nil {
- template.Value = ""
- }
- value = template.Value.(string)
- case "4":
- if template.Value == nil {
- template.Value = ""
- }
- var temp = &[]struct {
- SourceID string `json:"source_id"`
- FileName string `json:"file_name"`
- DownloadUrl string `json:"downloadUrl"`
- }{}
- err := json.Unmarshal([]byte(template.Value.(string)), temp)
- if err != nil {
- return false, key, ""
- }
- if isEmpty(temp) {
- value = ""
- return
- }
- for _, v := range *temp {
- value += fmt.Sprintf(" %s", v.FileName)
- }
- case "6":
- m, ok := template.ValueList.([]interface{})
- if ok == false {
- value = template.ValueList.(string)
- } else {
- var values string
- for _, v := range m {
- values += fmt.Sprintf(" %s", v)
- }
- value = values
- }
- case "7":
- key = ""
- case "8":
- }
- return template.Modeltype == "8", key, value
- }
- func SimpleTableReportExecutor(report *core.Report) {
- var (
- templates []Template
- unit = report.GetUnit()
- lineSpace = 0.01 * unit
- lineHight = 1.9 * unit
- )
- str := `[
- {"modelname":"所在公司","modeltype":"5","value":"中国航天科技九院"},
- {"modelname":"报销部门","modeltype":"1","value":"财务部"},
- {"modelname":"报销人","modeltype":"1","value":"钱伟长"},
- {"modelname":"职务","modeltype":"1","value":"技术总领导"},
- {"modelname":"项目名称","modeltype":"1","value":"航天科技人员培训"},
- {"modelname":"出差时间","modeltype":"2","value":"12.21"},
- {"modelname":"结束时间","modeltype":"2","value":"12.27"},
- {"modelname":"目的地","modeltype":"1","value":"青海金银滩"},
- {"modelname":"出差说明","modeltype":"2","value":"指导培训"},
- {"modelname":"实际出差时间和结束时间段","modeltype":"2"},
- {
- "modelname":"报销明细单",
- "modeltype":"8",
- "tableObj":{
- "columns":[
- {"columnsName":"出发时间","columnsType":"text"},
- {"columnsName":"出发地点","columnsType":"text"},
- {"columnsName":"到达时间","columnsType":"text"},
- {"columnsName":"到达地点","columnsType":"text"},
- {"columnsName":"交通工具","columnsType":"text"},
- {"columnsName":"事项","columnsType":"text"},
- {"columnsName":"交通费","columnsType":"number"},
- {"columnsName":"住宿费","columnsType":"number"},
- {"columnsName":"招待费","columnsType":"number"},
- {"columnsName":"补贴","columnsType":"number"},
- {"columnsName":"票据数","columnsType":"text"},
- {"columnsName":"票据序号","columnsType":"text"},
- {"columnsName":"备注","columnsType":"text"}
- ],
- "rows":[]
- },
- "tbodyArray":[],
- "tableTotalArr":["","","","","","","","","","","","",""]
- },
- {"modelname":"报销总额(小写)", "modeltype":"1","value":""},
- {"modelname":"报销总额(大写)","modeltype":"1","tableObj":{"columns":[],"rows":[]}},
- {"modelname":"超支金额","modeltype":"1","value":""},
- {"modelname":"应报金额","modeltype":"1","value":""},
- {
- "modelname":"调整金额",
- "modeltype":"8",
- "tableObj":{
- "columns":[
- {"columnsName":"交通费","columnsType":"text"},
- {"columnsName":"住宿费","columnsType":"text"},
- {"columnsName":"招待费","columnsType":"text"},
- {"columnsName":"补贴","columnsType":"text"}
- ],
- "rows":["调整","实报金额"]
- },
- "tbodyArray":[
- [
- {"columnsName":"交通费","rowsName":"调整"},
- {"columnsName":"住宿费","rowsName":"调整"},
- {"columnsName":"招待费","rowsName":"调整"},
- {"columnsName":"补贴","rowsName":"调整"}
- ],
- [
- {"columnsName":"交通费","rowsName":"实报金额"},
- {"columnsName":"住宿费","rowsName":"实报金额"},
- {"columnsName":"招待费","rowsName":"实报金额"},
- {"columnsName":"补贴","rowsName":"实报金额"}
- ]
- ],
- "tableTotalArr":["","","",""]
- },
- {"modelname":"备注","modeltype":"2", "value":""},
- {"modelname":"附件","modeltype":"4", "fileNameArr":[],"attachfileArr":[],"value":"[]"},
- {"modelname":"附单据","modeltype":"4","fileNameArr":[],"attachfileArr":[]}
- ]`
- json.Unmarshal([]byte(str), &templates)
- for _, template := range templates {
- isTable, key, value := handleTemplateRow(template)
- // key != "" 是过滤 Modeltype 为 "7"的情况
- if !isTable && key != "" {
- report.SetMargin(4*unit, 0)
- content := fmt.Sprintf("%s: %s", key, value)
- contentDiv := gopdf.NewDivWithWidth(80*unit, lineHight, lineSpace, report)
- contentDiv.SetFont(textFont).SetContent(content).GenerateAtomicCell()
- report.SetMargin(0, 1*unit)
- }
- // 处理表格
- if isTable {
- report.SetMargin(4*unit, 0)
- content := fmt.Sprintf("%s:", key)
- contentDiv := gopdf.NewDivWithWidth(80*unit, lineHight, lineSpace, report)
- contentDiv.SetFont(textFont).SetContent(content).GenerateAtomicCell()
- report.SetMargin(0, 0.5*unit)
- rows, cols, cells, hasRowName := handleTable(template)
- table := gopdf.NewTable(cols, rows, 100*unit, lineHight, report)
- for i := 0; i < rows; i++ {
- for j := 0; j < cols; j++ {
- cell := table.NewCell()
- element := gopdf.NewTextCell(table.GetColWidth(i, j), lineHight, lineSpace, report)
- element.SetFont(textFont)
- element.SetBorder(core.Scope{Left: 0.5 * unit, Top: 0.5 * unit})
- if i == 0 || j == 0 && hasRowName {
- element.HorizontalCentered()
- }
- element.SetContent(cells[i][j])
- cell.SetElement(element)
- }
- }
- table.GenerateAtomicCell()
- report.SetMargin(0, 1*unit)
- }
- }
- }
- func SimpleTableReport() {
- r := core.CreateReport()
- font1 := core.FontMap{
- FontName: FONT_MY,
- FileName: "ttf//microsoft.ttf",
- }
- font2 := core.FontMap{
- FontName: FONT_MD,
- FileName: "ttf//mplus-1p-bold.ttf",
- }
- r.SetFonts([]*core.FontMap{&font1, &font2})
- r.SetPage("A4", "mm", "P")
- r.RegisterExecutor(core.Executor(SimpleTableReportExecutor), core.Detail)
- r.Execute("simple_table_test.pdf")
- r.SaveAtomicCellText("simple_table_test.txt")
- }
- func TestComplexTableReport(t *testing.T) {
- SimpleTableReport()
- }
|