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)
func (f *File) SetRowOutlineLevel(sheet string, row int, level uint8) error

根据给定的工作表名称、行号和分级参数创建组。例如,在名为 Sheet1 的工作表的第 2 行创建 1 级分组。

Go-Excelize API源码阅读(二十七)——SetRowOutlineLevel、SetColOutlineLevel

err := f.SetRowOutlineLevel("Sheet1", 2, 1)

我们来看源码:

// 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)
}
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")
	prepareSheetXML(ws, 0, row)
	ws.SheetData.Row[row-1].OutlineLevel = level
	return nil
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)
func (f *File) SetColOutlineLevel(sheet, col string, level uint8) error

根据给定的工作表名称、列名称和分级参数创建组。例如,在名为 Sheet1 的工作表的 D 列创建 2 级分组。

Go-Excelize API源码阅读(二十七)——SetRowOutlineLevel、SetColOutlineLevel

err := f.SetColOutlineLevel("Sheet1", "D", 2)

现在来看看源码:

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
}

看第一部分:

	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.ColflatCols 用于平铺和检查工作表的列。

原文地址:https://cloud.tencent.com/developer/article/2139631

你可能想看:
分享给朋友: