質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

.NET Framework 4.0

Microsoft Windows用のソフトウェア開発環境/実行環境である .NET Frameworkの4番目のメジャーバージョンです。

Q&A

解決済

1回答

3300閲覧

C# Npoiを使用してエクセルファイルの1行の全取得ができない。途中で読み込みが止まっていた。

sueteacher

総合スコア48

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Windows Forms

Windows Forms(WinForms)はMicrosoft .NET フレームワークに含まれる視覚的なアプリケーションのプログラミングインターフェイス(API)です。WinFormsは管理されているコードの既存のWindowsのAPIをラップすることで元のMicrosoft Windowsのインターフェイスのエレメントにアクセスすることができます。

.NET Framework 4.0

Microsoft Windows用のソフトウェア開発環境/実行環境である .NET Frameworkの4番目のメジャーバージョンです。

0グッド

0クリップ

投稿2022/06/17 08:21

【質問】
1.Npoiを使用して1行すべての取得ができない。(Npoiの仕様??)
2.別で取得したList<string[]>の値を、リストビューの別の列に表示したい。(追加したい。)
3.エクセルファイルを1度で読み込みたいがエラーになる(先頭に空があるため)
【環境】
C# .netframework4.7 visual studio2022 Windows Form

【仮実装】
・Npoiでエクセルファイルを読み込み、変数に格納し、その後リストビューに表示
・1行がすごく長い列のため、ループ文を使用

【目的】
・エクセルファイル1行ずつ全取得後、使用するところだけ変数や配列に格納したい。(【例】1行取得したらG列目以降を格納または表示)
・検索後、検索した1行の{"文字列,文字列"}のところをリストビューに列に追加して別の1列としてにまとめたい。

【参考】
https://teratail.com/questions/8rmkh3qufecejj

【例】
・1行の列を700用意した所、1行の列の全取得数が695と合わなかった。
・列を500にしたとき、1行の列の全取得が496となってしまっている。

C#初心者学習中。
手厳しくお願い致します。

イメージ説明
イメージ説明

C#

1using System; 2using System.Collections.Generic; 3using System.ComponentModel; 4using System.Data; 5using System.Drawing; 6using System.Linq; 7using System.Text; 8using System.Threading.Tasks; 9using NPOI.SS.UserModel; 10using System.Windows.Forms; 11 12namespace WindowsFormsApp6 13{ 14 public partial class Form1 : Form 15 { 16 List<string[]> list = new List<string[]>(); 17 List<string[]> reslist = new List<string[]>(); 18 19 20 public Form1() 21 { 22 InitializeComponent(); 23 listView1.Columns.Add("No"); 24 listView1.Columns.Add("在庫場所"); 25 listView1.Columns.Add("取引先"); 26 listView1.Columns.Add("文字列,文字列"); 27 listView1.View = View.Details; 28 29 SetItems(); 30 31 } 32 33 private void SetItems() 34 { 35 36 // エクセルファイルを開く 37 var workbook = WorkbookFactory.Create(@"test.xlsx"); 38 39 // 対象シートを取得 40 var worksheet = workbook.GetSheet("sheet1"); 41 42 var items = new List<ListViewItem>(); 43 44 //7行目、8行目 45 var row1 = worksheet.GetRow(5); 46 var row2 = worksheet.GetRow(6); 47 var row3 = worksheet.GetRow(7); 48 49 // 1行目のセルの数を列数として扱う 50 var cellCount = row1?.Cells.Count ?? 0; 51 52 //左から6列目のセルから最後まで 53 for (var i = 6; i < cellCount; i++) 54 { 55 56 var cells = new[] { row1.GetCell(i), row2.GetCell(i),row3.GetCell(i) }; 57 var values = new string[] { "", "","" }; 58 59 // 1行目と2行目のセルの値を格納 60 for (var j = 0; j < 3; j++) 61 { 62 63 var cell = cells[j]; 64 65 //セルの型に応じたプロパティを参照する 66 switch (cell?.CellType ?? CellType.Unknown) 67 { 68 //セルの型がstringのとき 69 case CellType.String: 70 values[j] = cell.StringCellValue; 71 break; 72 //セルの型が数値のとき 73 case CellType.Numeric: 74 values[j] = Convert.ToString(cell.NumericCellValue); 75 break; 76 default: 77 //空を代入 78 values[j] = ""; 79 break; 80 } 81 82 } 83 84 // リストビューアイテムを作成 85 items.Add(new ListViewItem(values)); 86 } 87 88 // ブックを閉じる 89 workbook.Close(); 90 91 // リストビューをクリアして項目を一括追加 92 listView1.SuspendLayout(); 93 listView1.Items.Clear(); 94 listView1.Items.AddRange(items.ToArray()); 95 listView1.ResumeLayout(); 96 97 } 98 99 private void ExRead1() 100 { 101 //エクセルファイルを開いた 102 IWorkbook workbook = WorkbookFactory.Create(@"test.xlsx"); 103 //index1のシートを参照 104 ISheet worksheet = workbook.GetSheetAt(0); 105 //シートの行をworksheet.LastRowNum; で最終行まで参照 106 int lastRow = worksheet.LastRowNum; 107 //int i = 8 最初の行 から最後の行まで 108 for (int i = 8; i <= lastRow; i++) 109 { 110 //i番目の行を取得 111 IRow row = worksheet.GetRow(i); 112 //回して参照した値を格納 113 List<string> sv = new List<string>(); 114 //セルを0番目から(左から右に)ある数だけ回す。 115 for (int j = 0; j < row.Cells.Count; j++) 116 { 117 ICell cell = row?.GetCell(j); 118 119 //セルの型に応じたプロパティを参照する 120 if (cell == null) 121 { 122 sv.Add(""); 123 } 124 else 125 { 126 switch (cell.CellType) 127 { 128 //セルの型がstringのとき 129 case CellType.String: 130 //List<string>のsvに値を格納 131 sv.Add(cell.StringCellValue); 132 //switch文から抜ける 133 break; 134 //セルの型が数値のとき 135 case CellType.Numeric: 136 //数値をstringに変更し格納 137 sv.Add(Convert.ToString(cell.NumericCellValue)); 138 //switch文から抜ける 139 break; 140 //セルの中身が空 141 case CellType.Blank: 142 //空を代入 143 sv.Add(""); 144 //switch文から抜ける 145 break; 146 //case以外のとき(elseの役割) 147 default: 148 //空を代入 149 sv.Add(""); 150 //switch文から抜ける 151 break; 152 } 153 } 154 } 155 156 //1行のセルをすべて取り終わったあとにstringの値をstring[]に変換し、格納 157 list.Add(sv.ToArray()); 158 } 159 workbook.Close(); 160 } 161 private void Seachitem() 162 { 163 //検索のまわす。 164 foreach (string[] v in list) 165 { 166 //入力された文字とおなじのとき 167 if (textBox1.Text == v[1]) 168 { 169 label1.Text = v[1]; 170 label2.Text = v[2]; 171 reslist.Add(v); 172 } 173 174 } 175 } 176 177 private void button1_Click(object sender, EventArgs e) 178 { 179 ExRead1(); 180 Seachitem(); 181 182 List<string> lnsv = new List<string>(); 183 var lnitems = new List<ListViewItem>(); 184 185 //foreachで回す。 186 int j = 0; 187 foreach (string[] l in reslist) 188 { 189 lnitems.Add(new ListViewItem(l)); 190 for(int i = 0; i < l.Length; i++) 191 { 192 ListViewItem lvi = new ListViewItem(l[i]); 193 listView1.Items.Add(lvi); 194 } 195 196 } 197 198 199 } 200 } 201 202 203} 204

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YAmaGNZ

2022/06/17 11:18

空のセルが含まれてないのでは?
sueteacher

2022/06/20 10:49

返事が遅れてしまいすみません。 LastCellNumを使用したら最後まで読み取りができましたが、row1?の後ろではなく、for文の中での使用になるのでしょうか。 ------------修正してみた。 動いた。 // 1行目のセルの数を列数として扱う //LastCellNumにすることで最後まで取得できました。 var cellCount = row1?.LastCellNum ?? 0; ------------- -------------こちらだとエラーが発生 //左から6列目のセルから最後まで for (var i = 0; i < cellCount; i++) -------------
KOZ6.0

2022/06/20 11:42

row1?.LastCellNum と記述すると short? です。 row1 が null でないことが保証されているなら、row1.LastCellNum で良いでしょう。 for は、LastCellNum まで回さなければならないので for (var i = 0; i <= row1.LastCellNum; i++) となります。
guest

回答1

0

ベストアンサー

ちょっと答えになってしまいますがやりたいことは
・textbox1に商品名を入力して対象行の情報をlistview1に表示
・label1には商品名を表示
・label2には値段を表示
だと予想します。
プログラムは同じような処理がまとまってないので自分なりに修正してみました。
掲示してあるプログラムを大きくは以下のように修正しました。
・セルの値を文字列として取得する関数を追加
・画面を開いた時の処理は不要と考え、リストビューのみの初期化
・データの保持は行わず、button1の押下で検索&画面に結果表示
・try~finalyでbookを閉じる
という感じです。

示したコードで想定通り動いてしまうと勉強にはならないかもしれませんが、その場合は何とか自分のコードになるように努力してみてください。

※前回、回答してしまったのでフォローします。

C#

1 public partial class Form1 : Form { 2 3 public Form1() { 4 InitializeComponent(); 5 6 listView1.Columns.Add("No"); 7 listView1.Columns.Add("在庫場所"); 8 listView1.Columns.Add("取引先"); 9 listView1.Columns.Add("文字列,文字列"); 10 listView1.View = View.Details; 11 } 12 13 private void button1_Click(object sender, EventArgs e) { 14 15 listView1.SuspendLayout(); 16 SetItems(); 17 listView1.ResumeLayout(); 18 19 } 20 21 private void SetItems() { 22 23 listView1.Items.Clear(); 24 25 label1.Text = ""; 26 label2.Text = ""; 27 28 var targetItemName = textBox1.Text; 29 30 if (string.IsNullOrEmpty(targetItemName)) { 31 return; 32 } 33 34 // エクセルファイルを開く 35 var workbook = WorkbookFactory.Create(@"test.xlsx"); 36 37 try { 38 39 // 対象シートを取得 40 var worksheet = workbook.GetSheet("sheet1"); 41 42 var lastRowNum = worksheet.LastRowNum; 43 IRow dataRow = null; 44 45 for (var i = 8; i <= lastRowNum; i++) { 46 47 var row = worksheet.GetRow(i); 48 49 if (row == null) { 50 continue; 51 } 52 53 // 商品名取得 54 if (GetCellValue(row.GetCell(1)) != targetItemName) { 55 continue; 56 } 57 58 dataRow = row; 59 break; 60 } 61 62 // 商品名に一致した行が見つからない 63 if (dataRow == null) { 64 return; 65 } 66 67 var items = new List<ListViewItem>(); 68 69 // 商品名と金額を設定 70 label1.Text = GetCellValue(dataRow.GetCell(1)); 71 label2.Text = GetCellValue(dataRow.GetCell(2)); 72 73 // №(列)のセルの数を列数として扱う 74 var lastCellNum = dataRow.LastCellNum; 75 76 for (var i = 6; i <= lastCellNum; i++) { 77 78 var number = GetCellValue(worksheet.GetRow(5)?.GetCell(i)); 79 var zaiko = GetCellValue(worksheet.GetRow(6)?.GetCell(i)); 80 var torihikisaki = GetCellValue(worksheet.GetRow(7)?.GetCell(i)); 81 var data = GetCellValue(dataRow.GetCell(i)); 82 83 // すべて空のデータは対象外 84 if (string.IsNullOrEmpty(number) 85 && string.IsNullOrEmpty(zaiko) 86 && string.IsNullOrEmpty(torihikisaki) 87 && string.IsNullOrEmpty(data)) { 88 continue; 89 } 90 91 items.Add(new ListViewItem(new[] { number, zaiko, torihikisaki, data })); 92 } 93 94 if (items.Count == 0) { 95 return; 96 } 97 98 listView1.Items.AddRange(items.ToArray()); 99 100 } finally { 101 102 // ブックを閉じる 103 workbook.Close(); 104 105 } 106 107 } 108 109 /// <summary> 110 /// セルの値を文字列で取得 111 /// </summary> 112 /// <param name="cell">対象セル</param> 113 /// <returns>対象セルが存在し、セルの値が文字列か数値の場合はセルの値を示す文字列。それ以外は空文字。</returns> 114 private string GetCellValue(ICell cell) { 115 116 if (cell == null) { 117 return ""; 118 } 119 120 //セルの型に応じたプロパティを参照する 121 switch (cell.CellType) { 122 //セルの型がstringのとき 123 case CellType.String: 124 return cell.StringCellValue; 125 //セルの型が数値のとき 126 case CellType.Numeric: 127 return Convert.ToString(cell.NumericCellValue); 128 } 129 130 return ""; 131 } 132 133 }

投稿2022/06/20 11:44

編集2022/06/20 11:48
dekaaki

総合スコア292

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問