iT邦幫忙

2

NPOI 舊版之謎?

  • 分享至 

  • xImage

NPOI 使用 2.1.1 版
礙於難以言喻的限制
無法把 NPOI 更新到最新版本

使用 .xlsx 檔,當表格範本使用
可是
sheet.CopyRow(sourceIndex, targetIndex);
沒辦法用?
沒錯誤訊息,但是 targetIndex 的Row 抓到都是 null?

換個方向想,也許是舊版的NPOI有缺陷?
找個 .xls 檔用的 CopyRow 來改寫

出處: https://dotblogs.com.tw/kim66766/2011/04/09/npoi-copy-row
改寫成

    private void ExcelCopyRow(IWorkbook workbook, ISheet worksheet, int sourceRowNum, int destinationRowNum)
    {
        // Get the source / new row
        IRow newRow = worksheet.GetRow(destinationRowNum);
        IRow sourceRow = worksheet.GetRow(sourceRowNum);

        // If the row exist in destination, push down all rows by 1 else create a new row
        if (newRow != null)
        {
            worksheet.ShiftRows(destinationRowNum, worksheet.LastRowNum, 1);
        }
        else
        {
            newRow = worksheet.CreateRow(destinationRowNum);
        }

        // Loop through source columns to add to new row
        for (int i = 0; i < sourceRow.LastCellNum; i++)
        {
            // Grab a copy of the old/new cell
            ICell oldCell = sourceRow.GetCell(i);
            ICell newCell = newRow.CreateCell(i);

            // If the old cell is null jump to next cell
            if (oldCell == null)
            {
                newCell = null;
                continue;
            }

            // Copy style from old cell and apply to new cell
            ICellStyle newCellStyle = workbook.CreateCellStyle();
            newCellStyle.CloneStyleFrom(oldCell.CellStyle); ;
            newCell.CellStyle = newCellStyle;

            // If there is a cell comment, copy
            if (newCell.CellComment != null) newCell.CellComment = oldCell.CellComment;

            // If there is a cell hyperlink, copy
            if (oldCell.Hyperlink != null) newCell.Hyperlink = oldCell.Hyperlink;

            // Set the cell data type
            newCell.SetCellType(oldCell.CellType);

            // Set the cell data value
            switch (oldCell.CellType)
            {
                case CellType.Blank:
                    newCell.SetCellValue(oldCell.StringCellValue);
                    break;
                case CellType.Boolean:
                    newCell.SetCellValue(oldCell.BooleanCellValue);
                    break;
                case CellType.Error:
                    newCell.SetCellErrorValue(oldCell.ErrorCellValue);
                    break;
                case CellType.Formula:
                    newCell.SetCellFormula(oldCell.CellFormula);
                    break;
                case CellType.Numeric:
                    newCell.SetCellValue(oldCell.NumericCellValue);
                    break;
                case CellType.String:
                    newCell.SetCellValue(oldCell.RichStringCellValue);
                    break;
                case CellType.Unknown:
                    newCell.SetCellValue(oldCell.StringCellValue);
                    break;
            }
        }

        // If there are are any merged regions in the source row, copy to new row
        for (int i = 0; i < worksheet.NumMergedRegions; i++)
        {
            CellRangeAddress cellRangeAddress = worksheet.GetMergedRegion(i);
            if (cellRangeAddress.FirstRow == sourceRow.RowNum)
            {
                CellRangeAddress newCellRangeAddress = new CellRangeAddress(newRow.RowNum,
                                                                            (newRow.RowNum +
                                                                             (cellRangeAddress.FirstRow -
                                                                              cellRangeAddress.LastRow)),
                                                                            cellRangeAddress.FirstColumn,
                                                                            cellRangeAddress.LastColumn);
                worksheet.AddMergedRegion(newCellRangeAddress);
            }
        }

    }
    

結果還是一樣?
Row 抓到 0 ~ 30 的
31以後通通都是null
沒複製到? 有人遇過同樣的問題嗎?
想了4天了,找不出來問題出在哪裡?

看更多先前的討論...收起先前的討論...
player iT邦大師 1 級 ‧ 2023-02-13 18:37:24 檢舉
開Excel檢查
只有1頁
Row 1~32
到可是在NPOI只抓到Row 0~30 ? 好奇怪? 少掉的1個Row到哪去了?
player iT邦大師 1 級 ‧ 2023-02-14 11:50:37 檢舉
同一頁籤
還是複製不下去?
這當範本的Excel檔到底是怎樣了?
player iT邦大師 1 級 ‧ 2023-02-14 14:35:31 檢舉
在迴圈裡跑
IRow dataRow = sheet.CopyRow(sourceIndex, targetIndex);
確定有產生Row
但是接下來另一個迴圈
IRow dataRow = sheet.GetRow(rowIndex);
dataRow 直接都變成 null ?
可是 workbook.IsReadOnly 是 flase 沒有唯獨啊
player iT邦大師 1 級 ‧ 2023-02-14 17:41:53 檢舉
xls檔的
Row 有跑出來
但是Style 只能上限 4000 筆
有資料沒版面
套版失敗

xlsx 則是新增 Row時
就直接 Row 被吃掉變 null
看著舊版NPOI 有點頭痛了
player iT邦大師 1 級 ‧ 2023-02-15 11:56:45 檢舉
把來源與目的分開
自己重建Row
Style複製失敗
再補上一堆程式碼
跑到執行緒直接TimeOut
而且輸出的檔案Style也是壞掉的

再改用別的方法
用Excel開檔案
把原本的頁籤複製一份存檔 (想說是不是有什麼機制在保護,不讓我編輯新增Row?)
結果範本檔案在程式裡開不起來?
Wrong Local header signature: 0xE011CFD0
player iT邦大師 1 級 ‧ 2023-02-15 12:17:36 檢舉
using (MemoryStream ms = new MemoryStream())
{
using (FileStream file = new FileStream(ExcelFile, FileMode.Open, FileAccess.Read))
{
file.CopyTo(ms);
}

ms.Flush();
ms.Position = 0;
workbookDest = new XSSFWorkbook(ms); //這行跳 System.NullReferenceException ? 新改的範本檔案不能用?
}
player iT邦大師 1 級 ‧ 2023-02-17 14:29:47 檢舉
1. 改用 xls檔當範本,預先複製好30頁的表格並插入分頁,存成範本檔案
2.程式裡開範本檔案,只跑回圈做填值處理,並刪除多餘頁面
目前只卡在先存好暫存檔後,ASP.NET要輸出時,執行緒提早結束,瀏覽器收不到檔案?
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

0
JamesDoge
iT邦高手 1 級 ‧ 2023-02-16 20:06:15
最佳解答
private void ExcelCopyRow(IWorkbook workbook, ISheet worksheet, int sourceRowNum, int destinationRowNum)
{
    // Get the source / new row
    IRow newRow = worksheet.GetRow(destinationRowNum);
    IRow sourceRow = worksheet.GetRow(sourceRowNum);

    // If the row exist in destination, push down all rows by 1 else create a new row
    if (newRow != null)
    {
        worksheet.ShiftRows(destinationRowNum, worksheet.LastRowNum, 1);
    }
    else
    {
        newRow = worksheet.CreateRow(destinationRowNum);
        // Create cells in the target row to match the source row
        for (int i = 0; i < sourceRow.LastCellNum; i++)
        {
            newRow.CreateCell(i);
        }
    }

    // Loop through source columns to add to new row
    for (int i = 0; i < sourceRow.LastCellNum; i++)
    {
        // Grab a copy of the old/new cell
        ICell oldCell = sourceRow.GetCell(i);
        ICell newCell = newRow.GetCell(i);

        // Copy style from old cell and apply to new cell
        if (oldCell != null && newCell != null)
        {
            newCell.CellStyle = oldCell.CellStyle;
            newCell.CellComment = oldCell.CellComment;
            newCell.Hyperlink = oldCell.Hyperlink;
            newCell.SetCellType(oldCell.CellType);
            switch (oldCell.CellType)
            {
                case CellType.Blank:
                    newCell.SetCellValue(oldCell.StringCellValue);
                    break;
                case CellType.Boolean:
                    newCell.SetCellValue(oldCell.BooleanCellValue);
                    break;
                case CellType.Error:
                    newCell.SetCellErrorValue(oldCell.ErrorCellValue);
                    break;
                case CellType.Formula:
                    newCell.SetCellFormula(oldCell.CellFormula);
                    break;
                case CellType.Numeric:
                    newCell.SetCellValue(oldCell.NumericCellValue);
                    break;
                case CellType.String:
                    newCell.SetCellValue(oldCell.RichStringCellValue);
                    break;
                case CellType.Unknown:
                    newCell.SetCellValue(oldCell.StringCellValue);
                    break;
            }
        }
    }

    // If there are are any merged regions in the source row, copy to new row
    for (int i = 0; i < worksheet.NumMergedRegions; i++)
    {
        CellRangeAddress cellRangeAddress = worksheet.GetMergedRegion(i);
        if (cellRangeAddress.FirstRow == sourceRow.RowNum)
        {
            CellRangeAddress newCellRangeAddress = new CellRangeAddress(newRow.RowNum,
                                                                        (newRow.RowNum +
                                                                         (cellRangeAddress.FirstRow -
                                                                          cellRangeAddress.LastRow)),
                                                                        cellRangeAddress.FirstColumn,
                                                                        cellRangeAddress.LastColumn);
            worksheet.AddMergedRegion(newCellRangeAddress);
        }
    }
}

player iT邦大師 1 級 ‧ 2023-02-17 17:40:42 檢舉

先不試了
周末放假休息
先不想了
不過還是先謝了你的回答

player iT邦大師 1 級 ‧ 2023-02-20 11:45:03 檢舉

實驗失敗
你的code一樣導致cell的style複製不下去
原因不知道在哪裡?
當成版面檔案的 xlsx 降轉到 xls
問題好多

我要發表回答

立即登入回答