CRMEB 项目中 PHPExcel Worksheet(工作表)操作完全指南:访问、新增、复制与删除
后端电商前端【免费下载链接】CRMEBCRMEB开源商城免费开源多语言商城系统Tp6框架商城系统可商用包含小程序商城、H5商城、公众号商城、PC商城、App支持分销、拼团、砍价、秒杀、优惠券、积分、会员等级、小程序直播、页面DIY前后端分离方便二开更有详细使用文档、接口文档、数据字典、二开文档/视频教程欢迎大家提出宝贵意见和建议项目地址https://gitcode.com/gh_mirrors/cr/CRMEB点击查看免费下载工作表Worksheet是电子表格数据的基本载体PHPExcel 中所有单元格、公式、图片和图表都归属于某个工作表。本篇技术指南基于仓库内 PHPExcel 官方开发文档 06-Worksheets.md系统讲解 PHPExcel 工作簿Workbook与工作表Worksheet之间的组织关系覆盖工作表的索引访问、按名称访问、活动工作表切换、新增、复制、删除等全部核心 API同时结合仓库源码验证其底层实现并介绍 CRMEB 在 SpreadsheetExcelService 与 FileService 中基于其继任者 PhpSpreadsheet 的 Excel 导出/导入实践。读完本文你将能完整掌握 PHPExcel/PhpSpreadsheet 体系下的工作表生命周期管理并在二开中直接落地使用。工作表Worksheet是什么按照 PHPExcel 开发文档的定义工作表是单元格cell、公式formula、图片image、图表graph等对象的集合它保存了表征一份电子表格工作表所需的全部数据。一份工作簿PHPExcel 对象中可以包含一张或多张工作表这些工作表以“页签tab”的形式在 MS Excel 或其他电子表格程序中并列展示而 PHPExcel 通过一个内部数组workSheetCollection来维护它们的顺序。从源码可以印证这一点PHPExcel.php 的构造函数在实例化时就完成了工作簿与工作表集合的初始化public function __construct() { $this-uniqueID uniqid(); $this-calculationEngine new PHPExcel_Calculation($this); // Initialise worksheet collection and add one worksheet $this-workSheetCollection array(); $this-workSheetCollection[] new PHPExcel_Worksheet($this); $this-activeSheetIndex 0; ... }工作簿加载与默认工作表规则理解工作表操作之前需要先掌握 PHPExcel 加载数据时的工作表生成规则这与后续所有的索引访问密切相关从电子表格文件加载使用PHPExcel_IOFactory::load()读取 xlsx/xls 等文件时工作簿会载入文件里已有的全部工作表除非你在加载选项中指定只加载某些工作表。从非电子表格文件加载如果加载的是 CSV、HTML 等非表格文件或 SYLK 这类不按名称标识工作表的格式PHPExcel 会创建一个名为WorkSheet1的单一工作表来存放该文件的数据。实例化新工作簿当通过new PHPExcel()创建全新工作簿时PHPExcel 会自动创建一个名为WorkSheet1的工作表见上节构造函数的new PHPExcel_Worksheet($this)且activeSheetIndex被初始化为 0即这张默认表同时就是当前活动工作表。对应到 PHPExcel 后继者 PhpSpreadsheet 中\PhpOffice\PhpSpreadsheet\Spreadsheet的构造函数同样会创建一张默认工作表这一约定保持了兼容。查看工作簿中的工作表数量与名称PHPExcel 提供了两个用于了解工作簿工作表构成的方法方法返回类型说明getSheetCount()int返回工作簿中工作表的数量getSheetNames()string[]按工作表“页签”在 MS Excel 中的显示顺序返回所有工作表名称列表源码实现PHPExcel.php非常直观getSheetCount()直接返回count($this-workSheetCollection)getSheetNames()则遍历集合依次调用getSheet($i)-getTitle()收集标题后返回public function getSheetNames() { $returnValue array(); $worksheetCount $this-getSheetCount(); for ($i 0; $i $worksheetCount; $i) { $returnValue[] $this-getSheet($i)-getTitle(); } return $returnValue; }访问工作表按索引、按名称与活动工作表按索引访问getSheet()工作簿中的每张工作表都有一个索引位置该位置对应其在 MS Excel 打开工作簿时页签的显示顺序。使用getSheet()方法并传入索引即可取得对应的工作表对象// 获取工作簿中的第二张工作表 // 注意工作表索引从 0 开始 $objPHPExcel-getSheet(1);索引从 0 计数因此上例获取的是第二张表。如果不传索引参数则返回第一张工作表getSheet($pIndex 0)的默认参数。源码 getSheet() 在索引越界时会抛出PHPExcel_Exceptionif (!isset($this-workSheetCollection[$pIndex])) { $numSheets $this-getSheetCount(); throw new PHPExcel_Exception( Your requested sheet index: {$pIndex} is out of bounds. The actual number of sheets is {$numSheets}. ); }按名称访问getSheetByName()如果你需要按工作表标题来取表使用getSheetByName()并传入工作表名称// 获取名为 Worksheet 1 的工作表 $objPHPExcel-getSheetByName(Worksheet 1);注意该方法的匹配是严格全等即名称区分大小写且必须完全一致源码实现 会遍历工作表集合将$this-workSheetCollection[$i]-getTitle()与传入名称逐一比较找不到时返回null而非抛出异常。访问当前活动工作表getActiveSheet()任何时候工作簿中总有一张“当前活动工作表active worksheet”它就是在 MS Excel 中打开该工作簿时默认处于激活状态的页签。可以直接获取它// 获取当前活动工作表 $objPHPExcel-getActiveSheet();其实现为return $this-getSheet($this-activeSheetIndex);PHPExcel.php因此活动工作表的本质是“由 activeSheetIndex 指向的工作表”。切换活动工作表你可以按索引或按名称切换当前活动工作表两个方法都会返回切换后的工作表对象$objPHPExcel-setActiveSheetIndex(1); // 按索引切换到第二张表 $objPHPExcel-setActiveSheetIndexByName(My Data); // 按名称切换到指定表setActiveSheetIndex() 会先校验索引是否越界$pIndex $numSheets - 1时抛出异常再更新activeSheetIndexsetActiveSheetIndexByName() 则先调用getSheetByName()查表找到后转为索引再执行切换若工作簿中不存在该名称会抛出PHPExcel_Exception(Workbook does not contain sheet: . $pValue)。实战提示在 CRMEB 的 SpreadsheetExcelService::instance() 中\PhpOffice\PhpSpreadsheet\Spreadsheet实例化后立刻通过$spreadsheet-getActiveSheet()取得活动工作表并缓存到self::$sheet后续所有setCellValue、mergeCells、getStyle等操作都基于该活动表完成——这正是“活动工作表”模式在真实业务中的典型用法。新增工作表方式一createSheet()调用 PHPExcel 对象的createSheet()方法即可向工作簿追加一张新工作表$objPHPExcel-createSheet();不传参数时新工作表会被创建为工作簿中的“最后一张表”。传入索引参数时新工作表会插入到指定位置其后的所有工作表依次后移一位。命名规则通过该方法创建的工作表被命名为Worksheetn其中n是能保证标题唯一的最小数字例如已有Worksheet1、Worksheet2时新表会命名为Worksheet3。源码 createSheet() 先new PHPExcel_Worksheet($this)此时构造函数使用默认标题Worksheet再调用addSheet()完成插入。方式二new PHPExcel_Worksheet addSheet()你也可以先自行实例化一张工作表自由指定标题再用addSheet()把它插入工作簿// 创建一张名为 My Data 的新工作表 $myWorkSheet new PHPExcel_Worksheet($objPHPExcel, My Data); // 将 My Data 工作表作为工作簿的第一张表插入 $objPHPExcel-addSheet($myWorkSheet, 0);addSheet()的第二个参数是索引位置不传第二个参数时新工作表会被添加到现有最后一张工作表之后对应源码中$iSheetIndex null时执行$this-workSheetCollection[] $pSheet;PHPExcel.php。addSheet()内部还做了两件关键工作重名校验调用sheetNameExists()检查若工作簿中已存在同名工作表直接抛出PHPExcel_ExceptionWorkbook already contains a worksheet named ...父级绑定若新表的 parent 尚未绑定则调用rebindParent($this)将其挂接到当前工作簿Worksheet.php同时会迁移源工作簿的命名区域NamedRange。createSheet 默认命名的唯一性保证文档提到新表名为Worksheetn且n为“保证标题唯一的最小数字”。这一逻辑实际由 Worksheet::setTitle() 中的重名自动处理机制保证当检测到父工作簿中已存在同名表时会自动追加1、2……直到找到空位while ($this-parent-sheetNameExists($pValue . . $i)) $i;。若名称接近 31 字符上限还会在$i 10、$i 100时逐步截断到 28、27 字符确保追加序号后仍不超长。复制工作表同工作簿内复制clone addSheet()同一工作簿内的工作表复制做法是先clone要复制的工作表对象再用addSheet()把克隆对象插入工作簿$objClonedWorksheet clone $objPHPExcel-getSheetByName(Worksheet 1); $objClonedWorksheet-setTitle(Copy of Worksheet 1) $objPHPExcel-addSheet($objClonedWorksheet);克隆得到的对象与原表拥有相同的内容但标题必须另行设置setTitle()否则会触发 addSheet 的重名校验异常。跨工作簿复制addExternalSheet()把一张工作表从一个工作簿复制到另一个工作簿要更复杂因为 PHPExcel 需要同时复制两个工作簿之间的样式styling。为此官方提供了专门的addExternalSheet()方法$objClonedWorksheet clone $objPHPExcel1-getSheetByName(Worksheet 1); $objPHPExcel-addExternalSheet($objClonedWorksheet);从源码 addExternalSheet() 可以看到它的三步核心处理重名校验重名时抛出异常遍历源工作簿的cellXfCollection单元格格式集合将每个样式对象克隆并追加到当前工作簿通过rebindParent()把工作表迁移到当前工作簿并遍历其全部单元格把每个单元格的xfIndex加上源工作簿原有样式数量$cell-setXfIndex($cell-getXfIndex() $countCellXfs)从而保证样式索引在新工作簿中依然正确映射。复制时的重名责任无论是同工作簿复制还是跨工作簿复制确保工作表名称不重复都是开发者自己的责任。PHPExcel 会在复制导致重名时抛出异常addSheet与addExternalSheet均调用sheetNameExists()校验例如PHPExcel_Exception: Workbook already contains a worksheet named Worksheet 1. Rename this worksheet first.因此在复制后应立即调用setTitle()为副本改名。删除工作表删除工作表使用removeSheetByIndex()参数是目标工作表的索引位置。由于日常场景中我们往往只知道工作表对象或名称通常需要先通过getIndex()拿到索引再删除$sheetIndex $objPHPExcel-getIndex( $objPHPExcel-getSheetByName(Worksheet 1) ); $objPHPExcel-removeSheetByIndex($sheetIndex);getIndex()的实现比较特殊它通过比较对象的getHashCode()来定位工作表PHPExcel.php找不到时抛出PHPExcel_Exception(Sheet does not exist.)。而 removeSheetByIndex() 在索引越界时会抛出异常提示实际工作表数量正常情况通过array_splice移除集合中的对应元素。删除活动工作表的特殊行为如果删除的正是当前活动工作表那么前一个索引位置的工作表会成为新的活动工作表。这一行为对应源码中的活动索引调整逻辑——当activeSheetIndex $pIndex且被删工作表位于集合末尾时activeSheetIndex自动减 1if (($this-activeSheetIndex $pIndex) ($pIndex count($this-workSheetCollection) - 1)) { --$this-activeSheetIndex; }另外删除操作与 PHP 对象回收协同工作PHPExcel_Worksheet::__destruct()Worksheet.php会清理计算引擎中该表的公式缓存并调用disconnectCells()释放单元格集合内存。这也是 PhpSpreadsheet 中disconnectWorksheets()清理大文件内存的设计前身——CRMEB 在 SpreadsheetExcelService::excelSave() 导出完成后同样执行$spreadsheet-disconnectWorksheets()并unset($spreadsheet)释放内存。工作表明细标题合法性与边界约束工作表标题Title并非随意字符串PHPExcel 在底层做了严格的合法性校验理解这些约束可以避免二开时踩坑。校验逻辑位于 Worksheet::checkSheetTitle()非法字符以下 7 个可打印 ASCII 字符禁止出现在工作表标题中*、:、/、\、?、[、]。违反时抛出PHPExcel_Exception(Invalid character found in sheet title)。最大长度工作表标题最多允许31 个字符Excel 的页签命名上限超出时抛出PHPExcel_Exception(Maximum 31 characters allowed in sheet title.)。这两个约束贯穿整个工作表生命周期无论是new PHPExcel_Worksheet($pParent, $pTitle)构造Worksheet.php 中构造时即调用setTitle($pTitle, false)、还是后续的setTitle()改名都会经过同一套校验。此外新工作表创建后默认处于可见状态构造函数中调用setSheetState(PHPExcel_Worksheet::SHEETSTATE_VISIBLE)可通过setSheetState()/getSheetState()控制隐藏等状态。setTitle()还有一个容易被忽略的参数$updateFormulaCellReferences默认true改名时会同步更新工作簿内所有公式中对旧表名的引用通过PHPExcel_ReferenceHelper::updateNamedFormulas()因此在改表名后依赖公式引用的单元格仍能正确指向新名称。在 CRMEB 中的实际应用场景虽然 CRMEB 仓库将 PHPExcel 作为依赖保留在 crmeb/vendor/phpoffice/phpexcel 下但其核心导出/导入服务已迁移到 PHPExcel 的官方继任者 PhpSpreadsheetAPI 设计一脉相承工作表操作思想完全通用导出SpreadsheetExcelService 通过new Spreadsheet()getActiveSheet()获取默认活动表然后用setTitle()重命名表、setCellValue()写入标题/表头/数据、mergeCells()合并表头、getColumnDimension()-setWidth()设置列宽最终由PhpSpreadsheet\Writer\Xlsx写出文件或直接输出下载流。导入FileService::readExcel() 使用IOFactory::createReader($suffix)-load($filePath)载入 xlsx 文件随后执行$spreadsheet-getActiveSheet()获取活动工作表再通过getHighestRow()、getCellByColumnAndRow()按行列坐标逐行读取单元格值实现批量发货express类型与会员卡密card类型等导入功能。这两处对“活动工作表”的依赖正是本文所讲getActiveSheet()概念在生产代码中的直接体现——如果你需要在导入时处理多页签文件可进一步参考getSheetCount()、getSheetByName()、setActiveSheetIndexByName()在循环中切换工作表。小结PHPExcel 的工作表管理 API 围绕三个核心概念展开集合顺序索引、标题名称、活动状态activeSheetIndex。getSheet()/getSheetByName()/getActiveSheet()负责读取setActiveSheetIndex()/setActiveSheetIndexByName()负责切换createSheet()/addSheet()/addExternalSheet()负责新增与复制removeSheetByIndex()配合getIndex()负责删除。底层由workSheetCollection数组与activeSheetIndex指针共同驱动并配套 31 字符上限、7 个非法字符、重名自动加序号等约束机制。掌握这一整套模型后无论是直接用仓库内 PHPExcel 进行多页签报表开发还是参照 CRMEB 的 PhpSpreadsheet 服务做 Excel 导入导出二开都能游刃有余。深入阅读完整的 API 定义可查看 PHPExcel.php 与 Worksheet.phpCRMEB 的实战封装见 SpreadsheetExcelService.php 与 FileService.php。赞分享后端电商前端【免费下载链接】CRMEBCRMEB开源商城免费开源多语言商城系统Tp6框架商城系统可商用包含小程序商城、H5商城、公众号商城、PC商城、App支持分销、拼团、砍价、秒杀、优惠券、积分、会员等级、小程序直播、页面DIY前后端分离方便二开更有详细使用文档、接口文档、数据字典、二开文档/视频教程欢迎大家提出宝贵意见和建议项目地址https://gitcode.com/gh_mirrors/cr/CRMEB点击查看免费下载相关推荐PHPExcel 工作表Worksheet操作完全指南访问、创建、复制与删除的源码级解析PHPExcel 工作表Worksheet操作完全指南访问、创建、复制与删除的源码级解析 导读 在 PHPExcel 中工作表Worksheet是承后端数据处理PhpSpreadsheet 工作表Worksheet操作完全指南访问、添加、复制与删除PhpSpreadsheet 工作表Worksheet操作完全指南访问、添加、复制与删除 工作表Worksheet是 PhpSpreadsheet 中后端终极指南PHPExcel多工作表操作的完整技巧创建、复制与删除终极指南PHPExcel多工作表操作的完整技巧创建、复制与删除 PHPExcel是一款功能强大的PHP电子表格处理库能够轻松实现Excel文件的创建、读后端数据处理上一篇Dill项目常见问题解决方案下一篇SublimeLinter 常见问题解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考