当前位置:网站首页>Go-Excelize API源码阅读(六)—— DeleteSheet(sheet string)
Go-Excelize API源码阅读(六)—— DeleteSheet(sheet string)
2022-07-26 05:06:00 【ReganYue】
Go-Excelize API源码阅读(六)—— DeleteSheet(sheet string)
开源摘星计划(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 或更高版本。
二、DeleteSheet(sheet string)
func (f *File) DeleteSheet(sheet string)
根据给定的工作表名称删除指定工作表,谨慎使用此方法,这将会影响到与被删除工作表相关联的公式、引用、图表等元素。如果有其他组件引用了被删除工作表上的值,将会引发错误提示,甚至将会导致打开工作簿失败。当工作簿中仅包含一个工作表时,调用此方法无效。
func (f *File) DeleteSheet(name string) {
if f.SheetCount == 1 || f.GetSheetIndex(name) == -1 {
return
}
sheetName := trimSheetName(name)
wb := f.workbookReader()
wbRels := f.relsReader(f.getWorkbookRelsPath())
activeSheetName := f.GetSheetName(f.GetActiveSheetIndex())
deleteLocalSheetID := f.GetSheetIndex(name)
deleteAndAdjustDefinedNames(wb, deleteLocalSheetID)
for idx, sheet := range wb.Sheets.Sheet {
if !strings.EqualFold(sheet.Name, sheetName) {
continue
}
wb.Sheets.Sheet = append(wb.Sheets.Sheet[:idx], wb.Sheets.Sheet[idx+1:]...)
var sheetXML, rels string
if wbRels != nil {
for _, rel := range wbRels.Relationships {
if rel.ID == sheet.ID {
sheetXML = f.getWorksheetPath(rel.Target)
rels = "xl/worksheets/_rels/" + strings.TrimPrefix(f.sheetMap[sheetName], "xl/worksheets/") + ".rels"
}
}
}
target := f.deleteSheetFromWorkbookRels(sheet.ID)
f.deleteSheetFromContentTypes(target)
f.deleteCalcChain(sheet.SheetID, "")
delete(f.sheetMap, sheet.Name)
f.Pkg.Delete(sheetXML)
f.Pkg.Delete(rels)
f.Relationships.Delete(rels)
f.Sheet.Delete(sheetXML)
delete(f.xmlAttr, sheetXML)
f.SheetCount--
}
f.SetActiveSheet(f.GetSheetIndex(activeSheetName))
}
if f.SheetCount == 1 || f.GetSheetIndex(name) == -1 {
return
}
这段代码是保证当工作簿中仅包含一个工作表时,或者工作表的名称不正确时调用此方法无效。
func (f *File) GetSheetIndex(name string) int {
for index, sheet := range f.GetSheetList() {
if strings.EqualFold(sheet, trimSheetName(name)) {
return index
}
}
return -1
}
上面这段代码可知:当工作表的不在工作表列表中时GetSheetIndex返回-1。
sheetName := trimSheetName(name)的作用是获取工作表的名称。
func trimSheetName(name string) string {
if strings.ContainsAny(name, ":\\/?*[]") || utf8.RuneCountInString(name) > 31 {
r := make([]rune, 0, 31)
for _, v := range name {
switch v {
case 58, 92, 47, 63, 42, 91, 93: // replace :\/?*[]
continue
default:
r = append(r, v)
}
if len(r) == 31 {
break
}
}
name = string(r)
}
return name
}
不难看出,这个API的作用是裁剪\/?*[]这些内容。
wb := f.workbookReader()
wbRels := f.relsReader(f.getWorkbookRelsPath())
workbookReader 获取反序列化后的 workbook.xml 结构体指针。relsReader获取xl/worksheets/_rels/sheet%d.xml.rels反序列化后的结构体指针。
activeSheetName := f.GetSheetName(f.GetActiveSheetIndex())
deleteLocalSheetID := f.GetSheetIndex(name)
deleteAndAdjustDefinedNames(wb, deleteLocalSheetID)

GetActiveSheetIndex 提供了一个函数来获取电子表格的活动工作表索引。
如果未找到活动工作表,将返回整数 0。
关于ActiveSheet的内容可以在微软文档中查找:
Workbook.ActiveSheet 属性 (Excel) | Microsoft Docs
https://docs.microsoft.com/zh-cn/office/vba/api/excel.workbook.activesheet
activeSheetName就是活动工作表的名称,deleteLocalSheetID就是当前要删除的工作表的ID。
deleteAndAdjustDefinedNames 通过给定的工作表 ID 删除和调整工作簿中定义的名称。
func deleteAndAdjustDefinedNames(wb *xlsxWorkbook, deleteLocalSheetID int) {
if wb == nil || wb.DefinedNames == nil {
return
}
for idx := 0; idx < len(wb.DefinedNames.DefinedName); idx++ {
dn := wb.DefinedNames.DefinedName[idx]
if dn.LocalSheetID != nil {
localSheetID := *dn.LocalSheetID
if localSheetID == deleteLocalSheetID {
wb.DefinedNames.DefinedName = append(wb.DefinedNames.DefinedName[:idx], wb.DefinedNames.DefinedName[idx+1:]...)
idx--
} else if localSheetID > deleteLocalSheetID {
wb.DefinedNames.DefinedName[idx].LocalSheetID = intPtr(*dn.LocalSheetID - 1)
}
}
}
}
其中,下面这段代码用得巧妙:
for idx, sheet := range wb.Sheets.Sheet {
if !strings.EqualFold(sheet.Name, sheetName) {
continue
}
wb.Sheets.Sheet = append(wb.Sheets.Sheet[:idx], wb.Sheets.Sheet[idx+1:]...)
var sheetXML, rels string
if wbRels != nil {
for _, rel := range wbRels.Relationships {
if rel.ID == sheet.ID {
sheetXML = f.getWorksheetPath(rel.Target)
rels = "xl/worksheets/_rels/" + strings.TrimPrefix(f.sheetMap[sheetName], "xl/worksheets/") + ".rels"
}
}
}
target := f.deleteSheetFromWorkbookRels(sheet.ID)
f.deleteSheetFromContentTypes(target)
f.deleteCalcChain(sheet.SheetID, "")
delete(f.sheetMap, sheet.Name)
f.Pkg.Delete(sheetXML)
f.Pkg.Delete(rels)
f.Relationships.Delete(rels)
f.Sheet.Delete(sheetXML)
delete(f.xmlAttr, sheetXML)
f.SheetCount--
}
这段代码就是来删除sheetName对应的这个sheet,具体细节不再详述。
f.SetActiveSheet(f.GetSheetIndex(activeSheetName))就是继续设置活动工作表,应该还是之前的活动表。
三、结语
这里是老岳,这是Go语言相关源码的解读第六篇,我会不断努力,给大家带来更多类似的文章,恳请大家不吝赐教。
边栏推荐
- JVM第五讲:纵横数据如何应对洪峰推送
- 【Leetcode】493. Reverse Pairs
- AXI协议(4):AXI通道上的信号
- Icml2022 | imitation learning by evaluating the professional knowledge of the presenter
- AQS唤醒线程的时候为什么从后向前遍历,我懂了
- What are the demand management software for small and medium-sized enterprises
- How many holes have you stepped on in BigDecimal?
- Molecular skeleton transition tool -delinker introduction
- 基于遥感解译与GIS技术环境影响评价图件制作
- 关于负数表示的数值为什么比整数大1?
猜你喜欢

Improve reduce parallelism in shuffle operation

Security permission management details

分子骨架跃迁工具-DeLinker介绍

Black eat black? The man cracked the loopholes in the gambling website and "collected wool" for more than 100000 yuan per month

Seata submits at details in two stages

Compilation method of flood control evaluation report and flood modeling under the new guidelines

测试必备工具之Fiddler,你真的了解吗?

JVM Lecture 5: how to deal with peak push of vertical and horizontal data

When AQS wakes up the thread, I understand why it traverses from the back to the front

Week 6 Learning Representation: Word Embedding (symbolic →numeric)
随机推荐
基于R语言的Meta分析【全流程、不确定性分析】方法与Meta机器学习
【ACWing】2983. 玩具
注解@Autowired如何自动装配
Interprocess communication
【洛谷】P3919 【模板】可持久化线段树1(可持久化数组)
Redis expiration deletion strategy and memory obsolescence strategy
CLM陆面过程模式
Nacos registry
LeetCode链表问题——206.反转链表(一题一文学会链表)
[Luogu] p3919 [template] persistent segment tree 1 (persistent array)
公交站间的距离 : 简单模拟题
Ansible tutorial
Annotation @autowired how to assemble automatically
[acwing] 1268. Simple questions
Mathematical modeling and optimization analysis based on general optimization software gams
CMD operation command
域名解析过程全分析,就着文字理解更佳
Install nccl \ mpirun \ horovod \ NVIDIA tensorflow (3090ti)
[acwing] 2983. Toys
异步时父子线程间的ThreadLocal传递问题