iT邦幫忙

0

詢問C# 使用NPOI直向讀取Excel資料的寫法

  • 分享至 

  • xImage

各位先進好,

嘗試將Excel轉為純文字檔,但該Excel為直式紀錄資料
https://ithelp.ithome.com.tw/upload/images/20221230/20116501WVEZTnaGsX.jpg

但是取值後僅能橫式紀錄資料:12345王小名陳小宇林小芳黃小花蔡小帆男男女女男新北式台北市宜蘭縣桃園式新竹市

想詢問要如何才能直式取值:1王小名男新北市2陳小宇男台北市3林小芳女宜蘭縣4黃小花女桃園市5蔡小帆男新竹市

目前程式碼如下:

IWorkbook workbook = null;  //新建IWorkbook物件
FileStream fileStream = new FileStream(Source, FileMode.Open, FileAccess.Read);
workbook = new XSSFWorkbook(fileStream);  //xlsx資料讀入workbook
ISheet sheet = workbook.GetSheetAt(0);  //獲取第一個工作表
            
IRow row;//新建當前工作表行資料
for (int i = 0; i <= sheet.LastRowNum + 1; i++)  //對工作表每一行
{
  row = sheet.GetRow(i);   //row讀入第i行資料
  if (row != null)
      {
       for (int j = 1; j < row.LastCellNum; j++)  //對工作表每一列
          {                            
          Result = Result + row.GetCell(j).ToString();
          }
      }
}
FileStream fs = new FileStream(pa+@"\轉檔.txt", FileMode.Create, FileAccess.ReadWrite);
StreamWriter sw = new StreamWriter(fs, Encoding.Default);
sw.Write(Result);

一直認為會有IColumn這種寫法,但找不到相關資訊,就掉入死胡同了,盼能指點迷津/images/emoticon/emoticon06.gif

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
2
JamesDoge
iT邦高手 1 級 ‧ 2023-01-03 04:21:14
最佳解答

若要將資料從列旋轉到欄:
先將每一行的資料讀入到一個 List 中,再將這些 List 存入另一個 List<List> 中

IWorkbook workbook = null;  //新建IWorkbook物件
FileStream fileStream = new FileStream(Source, FileMode.Open, FileAccess.Read);
workbook = new XSSFWorkbook(fileStream);  //xlsx資料讀入workbook
ISheet sheet = workbook.GetSheetAt(0);  //獲取第一個工作表

// 建立一個空的 List<string> 用來儲存轉換後的資料
List<List<string>> data = new List<List<string>>();

IRow row;//新建當前工作表行資料
for (int i = 0; i <= sheet.LastRowNum + 1; i++)  //對工作表每一行
{
    row = sheet.GetRow(i);   //row讀入第i行資料
    if (row != null)
    {
        // 將 row.LastCellNum 個 cell 的資料讀入一個 List<string> 中
        List<string> rowData = new List<string>();
        for (int j = 0; j < row.LastCellNum; j++)
        {
            ICell cell = row.GetCell(j);
            rowData.Add(cell != null ? cell.ToString() : "");
        }

        // 將 List<string> 加入 data 中
        data.Add(rowData);
    }
}

// 將 data 中的資料寫入轉換後的檔案中
FileStream fs = new FileStream(pa+@"\轉檔.txt", FileMode.Create, FileAccess.ReadWrite);
StreamWriter sw = new StreamWriter(fs, Encoding.Default);
for (int i = 0; i < data[0].Count; i++)
{
    for (int j = 0; j < data.Count; j++)
    {
        sw.Write(data[j][i] + ",");
    }
    sw.WriteLine();
}

// 將資料寫入檔案後,要記得關閉 StreamWriter
sw.Close();
fufujane iT邦新手 5 級 ‧ 2023-01-04 15:15:55 檢舉

感謝解救,第一次理解到List的用法,有點像是T-SQL create view 的概念,成功了,感激不盡。

0
alien663
iT邦研究生 5 級 ‧ 2022-12-30 17:07:19

你這excel有夠反人類,不過還好微軟早就知道有這種事情會發生了。

將資料從列轉置 (旋轉) 到欄或反向操作

fufujane iT邦新手 5 級 ‧ 2023-01-04 15:13:29 檢舉

感謝回覆,在Excel操作確實蠻常用到轉置的,真心覺得這個功能太重要了,但是在C#裡難倒我了

0
水無痕
iT邦新手 3 級 ‧ 2023-01-03 09:37:27

給個範例

資料來源:
https://ithelp.ithome.com.tw/upload/images/20230103/20137005QP7iRTdZLX.png

語法

var templateFile = Path.Combine("C:\\temp\\test2.xlsx");
using var templateFileStream = new FileStream(templateFile, FileMode.Open, FileAccess.Read);

var workbook = new XSSFWorkbook(templateFileStream);
var sheet = workbook.GetSheetAt(0);

for (var rowIndex = 0; rowIndex <= sheet.LastRowNum; rowIndex++)
{
	for (var columnIndex = 0; columnIndex < sheet.GetRow(rowIndex).LastCellNum; columnIndex++)
	{
		var cell = sheet.GetRow(rowIndex).Cells[columnIndex];
        switch(cell.CellType)
        {
            case NPOI.SS.UserModel.CellType.Numeric:
                Console.WriteLine($"Column[{columnIndex}] Row[{rowIndex}]: {cell.NumericCellValue}");
                break;
			case NPOI.SS.UserModel.CellType.String:
				Console.WriteLine($"Column[{columnIndex}] Row[{rowIndex}]: {cell.StringCellValue}");
				break;
			case NPOI.SS.UserModel.CellType.Formula:
				Console.WriteLine($"Column[{columnIndex}] Row[{rowIndex}]: {cell.CellFormula}");
				break;
			case NPOI.SS.UserModel.CellType.Blank:
				Console.WriteLine($"Column[{columnIndex}] Row[{rowIndex}]: {cell.CellType}");
				break;
			case NPOI.SS.UserModel.CellType.Boolean:
				Console.WriteLine($"Column[{columnIndex}] Row[{rowIndex}]: {cell.BooleanCellValue}");
				break;
			case NPOI.SS.UserModel.CellType.Error:
				Console.WriteLine($"Column[{columnIndex}] Row[{rowIndex}]: {cell.ErrorCellValue}");
				break;
			default:
				Console.WriteLine($"Column[{columnIndex}] Row[{rowIndex}]: {cell.CellType}");
				break;

		}
	}
}

執行結果:

Column[0] Row[0]: Name
Column[1] Row[0]: A
Column[2] Row[0]: B
Column[3] Row[0]: C
Column[0] Row[1]: Id
Column[1] Row[1]: 1
Column[2] Row[1]: 2
Column[3] Row[1]: 3
fufujane iT邦新手 5 級 ‧ 2023-01-04 15:21:08 檢舉

感謝回覆,原來有這樣不用IROW的寫法,就能躲過雙層For只能先Row再Column了,非常感謝。

fufujane iT邦新手 5 級 ‧ 2023-01-11 11:53:42 檢舉

不好意思測試2個For條件顛倒會產生錯誤,想請問有辦法讓顯示的結果為直式讀取嗎,謝謝

Column[0] Row[0]: Name
Column[0] Row[1]: Id
Column[1] Row[0]: A
Column[1] Row[1]: 1
Column[2] Row[0]: B
Column[2] Row[1]: 2
Column[3] Row[0]: C
Column[3] Row[1]: 3

我要發表回答

立即登入回答