導入Excel文件的時候公式爲【#Ref!】應該怎麼解決?

前言

在我們使用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!】問題的全過程,如果您想了解更多詳細信息,歡迎點擊這裏查看。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章