返回

您需要的Go-Excelize API源码解读(七)—— CopySheet(from, to int)

后端

Go-Excelize API源码阅读(七)—— CopySheet(from, to int)

大家好,欢迎来到Go-Excelize API源码阅读系列文章的第七篇。在这一篇中,我们将探讨CopySheet(from, to int)函数的具体实现。

该函数的作用是提供了一个通过给出的源工作表和目标工作表索引来复制工作表的功能,此索引需要开发者自行确认是否存在。注意,目前不支持复制包含表格、图表或图片的工作簿,仅支持包含单元格值以及公式的工作表复制。

接下来,让我们详细看看CopySheet(from, to int)函数的实现代码:

func (f *File) CopySheet(from, to int) error {
	switch {
	case from < 1 || from > f.SheetCount():
		return errors.New("invalid from sheet index")
	case to < 1 || to > f.SheetCount()+1:
		return errors.New("invalid to sheet index")
	case from == to:
		return nil
	}

	ws := f.workSheetReader(from)
	if ws == nil {
		return errors.New("sheet not found")
	}
	sheetName := ws.Name
	for i, name := range f.SheetNames {
		if name == sheetName {
			sheetName = fmt.Sprintf("%s(%d)", name, i+1)
			break
		}
	}
	if ws.Hidden != 0 {
		ws.Hidden = 0
	}
	f.Sheets[to] = &xlsxWorksheet{
		Name:    sheetName,
		Hidden:  0,
		SheetID: f.addSheet(&f.SheetNames, sheetName, false),
	}
	err := f.duplicateSheet(ws, from, to)
	if err != nil {
		return err
	}
	for _, mergeCell := range f.MergeCells {
		if mergeCell.Worksheet == from {
			mergeCell.Worksheet = to
		}
	}
	return nil
}

首先,我们对from和to这两个参数进行了合法性检查,确保它们都在合理的范围内。如果from或to不合法,我们会返回一个错误。

接下来,我们通过workSheetReader(from)函数获取了源工作表的相关信息,包括工作表名称、隐藏状态等。

然后,我们为目标工作表分配了一个新的xlsxWorksheet结构,并设置了工作表名称、隐藏状态和工作表ID。

接下来,我们调用duplicateSheet(ws, from, to)函数来复制源工作表的内容到目标工作表。duplicateSheet(ws, from, to)函数的具体实现如下:

func (f *File) duplicateSheet(ws *xlsxWorksheet, from, to int) error {
	if ws == nil {
		return errors.New("sheet not found")
	}
	// Copy styles
	newStyleMap := make(map[int]int)
	for oldStyleID, cellXfs := range ws.CellXfs {
		newStyleID := f.newXF(oldStyleID)
		if newStyleID > 0 {
			newStyleMap[oldStyleID] = newStyleID
			for _, xf := range cellXfs {
				xf.XfId = newStyleID
			}
		}
	}
	for row, cols := range ws.Rows {
		for col, cell := range cols {
			if _, ok := cell.Style; ok {
				if newStyleID, ok := newStyleMap[cell.Style]; ok {
					cell.Style = newStyleID
				}
			}
			f.setCell(to, row, col, cell)
		}
	}
	for _, sheetPr := range ws.SheetPr {
		if sheetPr.OutlinePr != nil && f.Sheets[to].SheetPr.OutlinePr == nil {
			f.Sheets[to].SheetPr.OutlinePr = &xlsxOutlinePr{}
		}
	}
	// Copy dimensions
	if ws.Dimensions != nil {
		f.Sheets[to].Dimensions = ws.Dimensions.Duplicate()
	}
	if ws.Cols != nil {
		f.Sheets[to].Cols = make([]xlsxCol, len(ws.Cols))
		copy(f.Sheets[to].Cols, ws.Cols)
	}
	if ws.AutoFilter != nil {
		f.Sheets[to].AutoFilter = ws.AutoFilter.Duplicate()
	}
	if ws.ConditionalFormatting != nil {
		f.Sheets[to].ConditionalFormatting = make([]xlsxConditionalFormatting, len(ws.ConditionalFormatting))
		copy(f.Sheets[to].ConditionalFormatting, ws.ConditionalFormatting)
	}
	if ws.DataValidations != nil {
		f.Sheets[to].DataValidations = make([]xlsxDataValidation, len(ws.DataValidations))
		copy(f.Sheets[to].DataValidations, ws.DataValidations)
	}
	if ws.Hyperlinks != nil {
		f.Sheets[to].Hyperlinks = make([]xlsxHyperlink, len(ws.Hyperlinks))
		copy(f.Sheets[to].Hyperlinks, ws.Hyperlinks)
	}
	return nil
}

在duplicateSheet(ws, from, to)函数中,我们首先复制了源工作表的样式,然后复制了源工作表中的单元格内容。

接下来,我们复制了源工作表的尺寸、列、自动筛选、条件格式、数据有效性以及超链接等信息。

最后,我们返回nil,表示复制工作表成功。

通过以上介绍,我们对CopySheet(from, to int)函数的具体实现有了详细的了解。希望这篇文章对您有所帮助。