Go-Excelize API源码阅读(二十七)——SetRowOutlineLevel、SetColOutlineLevel
开源摘星计划(WeOpen Star) 是由腾源会 2022 年推出的全新项目,旨在为开源人提供成长激励,为开源项目提供成长支持,助力开发者更好地了解开源,更快地跨越鸿沟,参与到开源的具体贡献与实践中。
不管你是开源萌新,还是希望更深度参与开源贡献的老兵,跟随“开源摘星计划”开启你的开源之旅,从一篇学习笔记、到一段代码的提交,不断挖掘自己的潜能,最终成长为开源社区的“闪亮之星”。
我们将同你一起,探索更多的可能性!
项目地址: WeOpen-Star:https://github.com/weopenprojects/WeOpen-Star
一、Go-Excelize简介
Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基于 ECMA-376,ISO/IEC 29500 国际标准。可以使用它来读取、写入由 Microsoft Excel™ 2007 及以上版本创建的电子表格文档。支持 XLAM / XLSM / XLSX / XLTM / XLTX 等多种文档格式,高度兼容带有样式、图片(表)、透视表、切片器等复杂组件的文档,并提供流式读写 API,用于处理包含大规模数据的工作簿。可应用于各类报表平台、云计算、边缘计算等系统。使用本类库要求使用的 Go 语言为 1.15 或更高版本。
二、SetRowOutlineLevel(sheet string, row int, level uint8)
代码语言:javascript复制func (f *File) SetRowOutlineLevel(sheet string, row int, level uint8) error
根据给定的工作表名称、行号和分级参数创建组。例如,在名为 Sheet1 的工作表的第 2 行创建 1 级分组。
代码语言:javascript复制err := f.SetRowOutlineLevel("Sheet1", 2, 1)
我们来看源码:
代码语言:javascript复制// SetRowOutlineLevel provides a function to set outline level number of a
// single row by given worksheet name and Excel row number. The value of
// parameter 'level' is 1-7. For example, outline row 2 in Sheet1 to level 1:
//
// err := f.SetRowOutlineLevel("Sheet1", 2, 1)
//
func (f *File) SetRowOutlineLevel(sheet string, row int, level uint8) error {
if row < 1 {
return newInvalidRowNumberError(row)
}
if level > 7 || level < 1 {
return ErrOutlineLevel
}
ws, err := f.workSheetReader(sheet)
if err != nil {
return err
}
prepareSheetXML(ws, 0, row)
ws.SheetData.Row[row-1].OutlineLevel = level
return nil
}
如果行号row小于1,就返回newInvalidRowNumberError(row)
。
// newInvalidRowNumberError defined the error message on receiving the invalid
// row number.
func newInvalidRowNumberError(row int) error {
return fmt.Errorf("invalid row number %d", row)
}
代码语言:javascript复制if level > 7 || level < 1 {
return ErrOutlineLevel
}
如果level小于1或者大于7,就返回ErrOutlineLevel
。
// ErrOutlineLevel defined the error message on receive an invalid outline
// level number.
ErrOutlineLevel = errors.New("invalid outline level")
代码语言:javascript复制 prepareSheetXML(ws, 0, row)
ws.SheetData.Row[row-1].OutlineLevel = level
return nil
代码语言:javascript复制func prepareSheetXML(ws *xlsxWorksheet, col int, row int) {
ws.Lock()
defer ws.Unlock()
rowCount := len(ws.SheetData.Row)
sizeHint := 0
var ht float64
var customHeight bool
if ws.SheetFormatPr != nil && ws.SheetFormatPr.CustomHeight {
ht = ws.SheetFormatPr.DefaultRowHeight
customHeight = true
}
if rowCount > 0 {
sizeHint = len(ws.SheetData.Row[rowCount-1].C)
}
if rowCount < row {
// append missing rows
for rowIdx := rowCount; rowIdx < row; rowIdx {
ws.SheetData.Row = append(ws.SheetData.Row, xlsxRow{R: rowIdx 1, CustomHeight: customHeight, Ht: ht, C: make([]xlsxC, 0, sizeHint)})
}
}
rowData := &ws.SheetData.Row[row-1]
fillColumns(rowData, col, row)
}
prepareSheetXML
确保有足够的行,以及所选择的行中的列来接受数据。缺少的行会被回填,并给出它们的行号。我们以最后填充的行作为提示,以确定下一个行的大小。
ws.SheetData.Row[row-1].OutlineLevel = level
将该行的OutlineLevel属性设置为level。
三、SetColOutlineLevel(sheet, col string, level uint8)
代码语言:javascript复制func (f *File) SetColOutlineLevel(sheet, col string, level uint8) error
根据给定的工作表名称、列名称和分级参数创建组。例如,在名为 Sheet1 的工作表的 D 列创建 2 级分组。
代码语言:javascript复制err := f.SetColOutlineLevel("Sheet1", "D", 2)
现在来看看源码:
代码语言:javascript复制func (f *File) SetColOutlineLevel(sheet, col string, level uint8) error {
if level > 7 || level < 1 {
return ErrOutlineLevel
}
colNum, err := ColumnNameToNumber(col)
if err != nil {
return err
}
colData := xlsxCol{
Min: colNum,
Max: colNum,
OutlineLevel: level,
CustomWidth: true,
}
ws, err := f.workSheetReader(sheet)
if err != nil {
return err
}
if ws.Cols == nil {
cols := xlsxCols{}
cols.Col = append(cols.Col, colData)
ws.Cols = &cols
return err
}
ws.Cols.Col = flatCols(colData, ws.Cols.Col, func(fc, c xlsxCol) xlsxCol {
fc.BestFit = c.BestFit
fc.Collapsed = c.Collapsed
fc.CustomWidth = c.CustomWidth
fc.Hidden = c.Hidden
fc.Phonetic = c.Phonetic
fc.Style = c.Style
fc.Width = c.Width
return fc
})
return err
}
看第一部分:
代码语言:javascript复制 if level > 7 || level < 1 {
return ErrOutlineLevel
}
colNum, err := ColumnNameToNumber(col)
if err != nil {
return err
}
colData := xlsxCol{
Min: colNum,
Max: colNum,
OutlineLevel: level,
CustomWidth: true,
}
如果level大于7或者小于1,就会return一个ErrOutlineLevel。
接下来是colNum, err := ColumnNameToNumber(col)
// ColumnNameToNumber provides a function to convert Excel sheet column name
// to int. Column name case-insensitive. The function returns an error if
// column name incorrect.
//
// Example:
//
// excelize.ColumnNameToNumber("AK") // returns 37, nil
//
func ColumnNameToNumber(name string) (int, error) {
if len(name) == 0 {
return -1, newInvalidColumnNameError(name)
}
col := 0
multi := 1
for i := len(name) - 1; i >= 0; i-- {
r := name[i]
if r >= 'A' && r <= 'Z' {
col = int(r-'A' 1) * multi
} else if r >= 'a' && r <= 'z' {
col = int(r-'a' 1) * multi
} else {
return -1, newInvalidColumnNameError(name)
}
multi *= 26
}
if col > MaxColumns {
return -1, ErrColumnNumber
}
return col, nil
}
因为列号是字母,所以我们要讲字母转换为列号,此ColumnNameToNumber(name string)
便是将字母列名转换为列号。
创建一个变量名为colData的xlsxCol对象。
看看第二部分:
ws, err := f.workSheetReader(sheet)
if err != nil {
return err
}
if ws.Cols == nil {
cols := xlsxCols{}
cols.Col = append(cols.Col, colData)
ws.Cols = &cols
return err
}
ws.Cols.Col = flatCols(colData, ws.Cols.Col, func(fc, c xlsxCol) xlsxCol {
fc.BestFit = c.BestFit
fc.Collapsed = c.Collapsed
fc.CustomWidth = c.CustomWidth
fc.Hidden = c.Hidden
fc.Phonetic = c.Phonetic
fc.Style = c.Style
fc.Width = c.Width
return fc
})
return err
如果工作簿的列数为空,我们就新建一个xlsxCols
对象,然后加入cols.Col
。
flatCols
用于平铺和检查工作表的列。