Go-Excelize API 源码阅读(七)—— CopySheet(from, to int)
一、Go-Excelize 简介
Excelize 是 Go 语言编写的用于操作 Office Excel 文档基础库,基于 ECMA-376,ISO/IEC 29500 国际标准。可以使用它来读取、写入由 Microsoft Excel™ 2007 及以上版本创建的电子表格文档。支持 XLAM / XLSM / XLSX / XLTM / XLTX 等多种文档格式,高度兼容带有样式、图片(表)、透视表、切片器等复杂组件的文档,并提供流式读写 API,用于处理包含大规模数据的工作簿。可应用于各类报表平台、云计算、边缘计算等系统。使用本类库要求使用的 Go 语言为 1.15 或更高版本。
二、CopySheet(from, to int)、
func (f *File) CopySheet(from, to int) error
该 API 的作用是提供了一个通过给出的源工作表和目标工作表索引来复制工作表的功能,此索引需要开发者自行确认是否存在。注意,目前不支持复制包含表格、图表或图片的工作簿,仅支持包含单元格值以及公式的工作表复制。
使用案例:
sheet_index := f.NewSheet("Sheet2")
err := f.CopySheet(1, sheet_index)
复制代码
直接上手读源码:
func (f *File) CopySheet(from, to int) error {
if from < 0 || to < 0 || from == to || f.GetSheetName(from) == "" || f.GetSheetName(to) == "" {
return ErrSheetIdx
}
return f.copySheet(from, to)
}
复制代码
此函数应该是给copySheet
过滤一些索引错误的情况。比如:
源工作表索引小于 0 或目标工作表索引小于 0。
源工作表索引等于目标工作表索引。
源工作表不存在或者目标工作表不存在
然后调用copySheet
。
接下来直接读copySheet
的源码:
unc (f *File) copySheet(from, to int) error {
fromSheet := f.GetSheetName(from)
sheet, err := f.workSheetReader(fromSheet)
if err != nil {
return err
}
worksheet := deepcopy.Copy(sheet).(*xlsxWorksheet)
toSheetID := strconv.Itoa(f.getSheetID(f.GetSheetName(to)))
sheetXMLPath := "xl/worksheets/sheet" + toSheetID + ".xml"
if len(worksheet.SheetViews.SheetView) > 0 {
worksheet.SheetViews.SheetView[0].TabSelected = false
}
worksheet.Drawing = nil
worksheet.TableParts = nil
worksheet.PageSetUp = nil
f.Sheet.Store(sheetXMLPath, worksheet)
toRels := "xl/worksheets/_rels/sheet" + toSheetID + ".xml.rels"
fromRels := "xl/worksheets/_rels/sheet" + strconv.Itoa(f.getSheetID(fromSheet)) + ".xml.rels"
if rels, ok := f.Pkg.Load(fromRels); ok && rels != nil {
f.Pkg.Store(toRels, rels.([]byte))
}
fromSheetXMLPath := f.sheetMap[trimSheetName(fromSheet)]
fromSheetAttr := f.xmlAttr[fromSheetXMLPath]
f.xmlAttr[sheetXMLPath] = fromSheetAttr
return err
}
复制代码
看第一部分:
这部分是获取源工作表名字,然后读取源工作表。
嗯,我们继续。
worksheet := deepcopy.Copy(sheet).(*xlsxWorksheet)
复制代码
这里调用了github.com/mohae/deepcopy
包。
func Copy(src interface{}) interface{} {
if src == nil {
return nil
}
// Make the interface a reflect.Value
original := reflect.ValueOf(src)
// Make a copy of the same type as the original.
cpy := reflect.New(original.Type()).Elem()
// Recursively copy the original.
copyRecursive(original, cpy)
// Return the copy as an interface.
return cpy.Interface()
}
复制代码
Copy 将传递给它的对象创建一个深度拷贝,并在一个 interface {}中返回该拷贝。 返回的值将需要被断言为正确的类型。
接下来是获取目标工作表 ID,并拼凑目标工作表 XML 路径。
如果 xml 文件中 SheetView 参数所对应的sheetView
长度大于 0,这个参数是[]xlsxSheetView 类型,应该是工作表视图集合。此处当视图个数大于 0,就将第 1 个视图的TabSelected
参数置为false
.TabSelected
找了找微软的文档,没有说明是干什么用的。此处笔者猜测是点击一下单元格时强调的那个框框对应的参数。
接下来是给深拷贝过来的工作表的三个参数初始化。然后以sheetXMLPath
为键,worksheet
为值,存入目标工作表 Map:Sheet
。
这部分是处理 rels 文件的拷贝。
此处应是拷贝工作表的属性。
三、结语
这里是老岳,这是 Go 语言相关源码的解读第七篇,我会不断努力,给大家带来更多类似的文章,恳请大家不吝赐教。
评论