前言

在我们使用Excel时,经常会遇到一个问题,就是导入Excel时公式显示为【#Ref!】的情况。这通常是因为公式中引用的单元格已被删除或对应的工作表被删除,导致原公式无法识别对应的参数而显示为【#Ref!】。

比如在一张Excel表中,sheet1 中 A1 单元格的公式为‘=Sheet2!B1’,如果 Sheet2 由于各种历史原因丢失,那么此时 sheet1 中 A1 计算结果为【#Ref!】,如果此时想查找到 Sheet2 怎么办呢?今天小编就将为大家介绍如何用葡萄城公司的Java API 组件——GrapeCity Documents for Excel(以下简称GcExcel)来查找丢失的Sheet页。

具体操作步骤

1)准备

首先创建公式

Workbook workbook = new Workbook();
IWorksheet workSheet = workbook.getWorksheets().get(0);
workSheet.setName("sheet1");
workSheet.getRange(1, 1).setFormula("sheet2!F7");
workSheet.getRange(3, 3).setFormula("Sheet3!A1");

2)查找

接下来,通过Find进行遍历查询所有的【#Ref!】公式,GcExcel提供了各种类型的查找替换。

FindOptions tempVar = new FindOptions();
//设置通过文本查找
tempVar.setLookIn(FindLookIn.Texts);
IRange range = null;
do {
range = searchRange.find("Ref", range, tempVar);
if (range == null) {
break;
} else {
//在这里做相应的逻辑
}
} while (true);

上述代码是查找替换的基础代码,我们发现上述代码 searchRange 未定义,searchRange 可以是整个 sheet, 也可以是一片区域,接下来我们定义searchRange 。

3)特殊单元格

GcExcel 提供了找到错误公式的能力,通过 specialCells 可以查找到错误公式,并返回错误公式的区域为第二步中的searchRange变量 。

IRange searchRange = workSheet.getCells().specialCells(SpecialCellType.Formulas, SpecialCellsValue.Errors);

现在我们已经找到了对应的所有为【#Ref!】的单元格,接下来开始做查找成功之后的逻辑。

4)公式解析

查找成功后,可以通过 range.getFormula() 获取到公式,接下来对公式进行解析,由于 Excel 公式有的简单,有的复杂,不能单纯判断等号后,感叹号前的字符串为sheet 名称,我们要通过公式树去遍历解析。

GcExcel 提供了公式解析器,调用 parse 拿到公式树,之后可以通过 getWorksheetName 获取 sheetName,相关代码如下:

//将公式中等号去掉,并进行解析
FormulaSyntaxTree syntaxTree = FormulaSyntaxTree.Parse(range.getFormula().replaceFirst("=", ""));
addNotFoundSheet(syntaxTree.getRoot(), workbook);

addNotFoundSheet 定义如下:

private static void addNotFoundSheet(SyntaxNode node, Workbook workbook) {
if (node == null) {
return;
}
if (node instanceof ReferenceNode) {
String sheetName = ((ReferenceNode) node).getReference().getWorksheetName();
if (workbook.getWorksheets().get(sheetName) == null) {
IWorksheet tempSheet = workbook.getWorksheets().add();
tempSheet.setName(sheetName);
}
}
for (SyntaxNode child : node.getChildren()) {
addNotFoundSheet(child, workbook);
}
}

在上述代码中首先判断node是否是 ReferenceNode 类型,如果是的话,通过 node.getReference().getWorksheetName() 获取 sheetName,并判断当前工作簿是否存在此sheet,如果不存在则进行添加。

处理后,对其子节点进行递归判断,重复上述步骤,直到 node 节点为 null,退出递归查询。

最后附上完整版的代码:

public static void main(String[] args) throws Exception {
Workbook workbook = new Workbook();
IWorksheet workSheet = workbook.getWorksheets().get(0);
workSheet.setName("sheet1");
workSheet.getRange(1, 1).setFormula("sheet2!F7");
workSheet.getRange(3, 3).setFormula("Sheet3!A1"); FindOptions tempVar = new FindOptions();
tempVar.setLookIn(FindLookIn.Texts);
IRange searchRange = workSheet.getCells().specialCells(SpecialCellType.Formulas, SpecialCellsValue.Errors); IRange range = null;
do {
range = searchRange.find("Ref", range, tempVar);
if (range == null) {
break;
} else {
FormulaSyntaxTree syntaxTree = FormulaSyntaxTree.Parse(range.getFormula().replaceFirst("=", ""));
addNotFoundSheet(syntaxTree.getRoot(), workbook);
}
} while (true); } private static void addNotFoundSheet(SyntaxNode node, Workbook workbook) {
if (node == null) {
return;
}
if (node instanceof ReferenceNode) {
String sheetName = ((ReferenceNode) node).getReference().getWorksheetName();
if (workbook.getWorksheets().get(sheetName) == null) {
IWorksheet tempSheet = workbook.getWorksheets().add();
tempSheet.setName(sheetName);
}
}
for (SyntaxNode child : node.getChildren()) {
addNotFoundSheet(child, workbook);
}
}

通过上述代码,可以查找到”sheet2“与”sheet3“,并进行添加。

总结

以上就是使用GcExcel解决导入Excel文件的时候公式为【#Ref!】问题的全过程,如果您想了解更多详细信息,欢迎点击这里查看。



扩展链接:

如何使用 Blazor 框架在前端浏览器中导入/导出 Excel XLSX

简便实用:在 ASP.NET Core 中实现 PDF 的加载与显示

如何在.NET电子表格应用程序中创建流程图

导入Excel文件的时候公式为【#Ref!】应该怎么解决?的更多相关文章

  1. .Net MVC 导入导出Excel总结(三种导出Excel方法,一种导入Excel方法) 通过MVC控制器导出导入Excel文件(可用于java SSH架构)

    .Net MVC  导入导出Excel总结(三种导出Excel方法,一种导入Excel方法) [原文地址] 通过MVC控制器导出导入Excel文件(可用于java SSH架构)   public cl ...

  2. Java POI导入Excel文件

    今天在公司需要做个导入Excel文件的功能,所以研究了一下,参考网上的一些资料总算是做出来了,在此记录一下防止以后忘记怎么弄. 本人用的是poi3.8,所以需要的JAR包如下: poi-3.8.jar ...

  3. phpexcel导入excel文件报the filename xxx is not recognised as an OLE file错误。

    工作中频繁会用phpexcel类导入excel文件的数据到数据库,目前常用的excel文件格式有:xls.csv.xlsx. 刚开始,针对xls文件,使用如下程序,能正常运行: $objReader ...

  4. YII使用PHPExcel导入Excel文件的方法

    1.下载phpexcel,将压缩包中的classes复制到protected/extensions下并修改为PHPExcel. 2.修改YII配置文件config/main.php 'import'= ...

  5. springMVC(5)---导入excel文件数据到数据库

    springMVC(5)---导入excel文件数据到数据库 上一篇文章写了从数据库导出数据到excel文件,这篇文章悄悄相反,写的是导入excel文件数据到数据库.上一篇链接:springMVC(4 ...

  6. excel数据 入库mysql 和 mysql数据 导入excel文件

    1.excel数据入库mysql 首先准备excel文件, 标红的地方需要留意,一个是字段名所在行,一个表名对应页: 然后私用mysql工具 navicat, 选择数据库,然后导入文件, 选中相应ex ...

  7. java后端导入excel模板和导入excel文件去读数据

    模板转载地址:https://www.cnblogs.com/zhangyangtao/p/9802948.html 直接上代码(我是基于ssm写的demo,导入文件目前只能读取.xls后缀的exce ...

  8. C# Aspose.Cells方式导入Excel文件

    读取Excel 类 我返回的是DataTable 类型 也可以返回DataSet类型 public class XlsFileHelper { public DataTable ImportExcel ...

  9. 利用kettle组件导入excel文件到数据库

    利用kettle组件导入excel文件到数据库 1.     实现目标 把excel文件内容导入到目标表中:然后用java调用kettle的转换.excel文件的内容仅仅有两列,示比例如以下: wat ...

  10. PLSQL导入Excel文件预览不到数据行问题

    今天,从Excel导入Oracle一些数据,在导入的过程中,遇到一个问题,Excel里面有好几万条数据,但是通过PLSQL导入向导导入Excel文件之后,在PLSQL里却预览不到数据行,只能看见标题行 ...

随机推荐

  1. js中forEach的用法、forEach如何跳出循环、forEach与for之间的区别

    定义和用法 forEach() 调用数组的每个元素,并将元素传递给回调函数. 注意: forEach() 对于空数组是不会执行回调函数的. 用法: array.forEach(function(cur ...

  2. 【发现一个小问题】坑爹的官方日志库`golang.org/x/exp/slog`,凭啥不让我设置debug级别日志

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 一个代码使用了官方的日志库"golang.org ...

  3. TortoiseGit 常见问题汇总

    1.test分支修改后合并到master分支 1)切换本地分支到master分支 2)TortoiseGit --->  merge,选择远程分支test 提交到远程分支master 2.将远程 ...

  4. windwos10-11打开任意文件弹出警告

    如下打开exe或者视频.图片都弹出警告 解决方案输入快捷键win+s换出搜索框 输入Internet 选项 进入安全选项点击自定义级别 找到,加载应用程序和不安全文件 勾选启用(不安全) 然后确定-在 ...

  5. windows幻灯片壁纸

    设置为10秒 win+r输入regedit 查找路径 HKEY_CURRENT_USER\Control Panel\Personalization\Desktop Slideshow 修改inter ...

  6. 全新Self-RAG框架亮相,自适应检索增强助力超越ChatGPT与Llama2,提升事实性与引用准确性

    全新Self-RAG框架亮相,自适应检索增强助力超越ChatGPT与Llama2,提升事实性与引用准确性 1. 基本思想 大型语言模型(LLMs)具有出色的能力,但由于完全依赖其内部的参数化知识,它们 ...

  7. 移动端跨平台动效工具Lottie, PAG的使用

    动效工具Lottie   Lottie 是 Airbnb 开源的一套跨平台的完整的动画效果解决方案,设计师可以使用 Adobe After Effects 设计出漂亮的动画之后,使用 Lottic 提 ...

  8. Ubuntu22.04 & Win11 双系统hibernate热切换实现

    Ubuntu22.04 & Win11 双系统hibernate热切换实现 目录 Ubuntu22.04 & Win11 双系统hibernate热切换实现 修改交换分区或交换文件 修 ...

  9. 苹果正在测试新款Mac mini:搭载M3芯片 配备24GB大内存

    据悉苹果目前正在测试新的Mac机型,亮点是采用最新的M3芯片. 据报道,首款搭载M3芯片的设备应该是13英寸的MacBook Pro和重新设计的MacBook Air,Mac mini机型并不在名单上 ...

  10. OGG-将PostgreSQL通过OGG_BigData同步到Kafka后数据存在8小时时间差

    问题描述: 将PostgreSQL通过OGG_BigData同步到Kafka后数据存在8小时时间差. 问题原因: kafka.properties中的参数goldengate.userexit.tim ...