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

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

新規登録して質問してみよう
ただいま回答率
86.02%
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

解決済

C# エクセルファイルの複数の列を持つ2行をListViewで2列に表示したい

sueteacher
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番目のメジャーバージョンです。

1回答

0グッド

0クリップ

463閲覧

投稿2022/06/13 10:16

編集2022/06/13 10:25

【質問】
・指定した行(2行)をListViewで2列に分けたい
・1行目は1列目、2行目は2列目をListViewで表示したい

【目的】
・エクセルファイルの行を指定し、繰り返し文で列をすべて取得。その後、行ごとに1列ずつ表示したい(※今回は2行取得したので、1行目は1列目、2行目は2列目にしたい。)
・エクセルで指定した行の列は400列ある。
・2行の列は同じ数。

【相談前実装】
・1行に対し、ループで回し。List<string[]>に格納をし、[0]と[1]のforeach文でまわし、listView1.Items.Addに追加した。が、かさなってしまったため。subItems.addも用いましたが、行並びになってしまった。

【環境】
・C# .net framework4.7 visual studio2022 windowsform

よろしくお願いいたします。

C#

1using System; 2using System.Collections.Generic; 3using System.ComponentModel; 4using System.Data; 5using System.Drawing; 6using System.Linq; 7using NPOI.SS.UserModel; 8using System.Text; 9using System.Threading.Tasks; 10using System.Windows.Forms; 11 12namespace test 13{ 14 public partial class Form4 : Form 15 { 16 List<string[]> datalists = new List<string[]>(); 17 public Form4() 18 { 19 InitializeComponent(); 20 21 datalists.Clear(); 22 23 //エクセルファイルを開いた 24 IWorkbook workbook = WorkbookFactory.Create(@"エクセルファイル"); 25 //シート2を参照 26 ISheet worksheet = workbook.GetSheetAt(1); 27 //シートの行をworksheet.LastRowNum; で最終行まで参照 28 int lastRow = worksheet.LastRowNum; 29 //int i = 8 パラメータ値の行からアドレスの行まで 30 //8行目から9行目までの2行を取得 31 for (int i = 8; i <= 9; i++) 32 { 33 //i番目の行を取得 34 IRow row = worksheet.GetRow(i); 35 //回して参照した値を格納 36 List<string> sv = new List<string>(); 37 //セルを4番目から(左から右に)ある数だけ回す。 38 //空白を避けるため。 39 for (int j = 4; j < row.Cells.Count; j++) 40 { 41 ICell cell = row?.GetCell(j); 42 43 //セルの型に応じたプロパティを参照する 44 45 switch (cell.CellType) 46 { 47 //セルの型がstringのとき 48 case CellType.String: 49 //List<string>のsvに値を格納 50 sv.Add(cell.StringCellValue); 51 //switch文から抜ける 52 break; 53 //セルの型が数値のとき 54 case CellType.Numeric: 55 //数値をstringに変更し格納 56 sv.Add(Convert.ToString(cell.NumericCellValue)); 57 //switch文から抜ける 58 break; 59 //セルの中身が空 60 case CellType.Blank: 61 //空を代入 62 sv.Add(""); 63 //switch文から抜ける 64 break; 65 //case以外のとき(elseの役割) 66 default: 67 //空を代入 68 sv.Add(""); 69 //switch文から抜ける 70 break; 71 } 72 } 73 74 //1行のセルをすべて取り終わったあとにstringの値をstring[]に変換し、格納 75 datalists.Add(sv.ToArray()); 76 } 77 //シート2を閉じる 78 workbook.CloneSheet(1); 79 workbook.Close(); 80 81 82 83 foreach (string list in datalists[0]) 84 { 85 86 listView1.Items.Add(list); 87 } 88 foreach (string lists in datalists[1]) 89 { 90 listView1.Items.Add(lists); 91 } 92 93 } 94 } 95}

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

2022/06/13 12:35

こちらの質問が他のユーザーから「やってほしいことだけを記載した丸投げの質問」という指摘を受けました。

sueteacher

2022/06/14 01:18

teratailは「プログラミングに関する問題解決を行う場」です プログラミングに関して本当に困っている人をサポートすること、また、価値のあるコンテンツを世の中に残し届けることを目的としています。

回答1

1

ベストアンサー

誰も回答しないようなので小言とフォローを

1.ListViewに複数列を表示

subItems.addも使用したとなってますが使い方を間違ってませんか?
・ListViewの表示形式を詳細モードにしましたか?
・ListViewの指定行のSubItemsにちゃんと設定しましたか?

2.nullの扱い

C#

1ICell cell = row?.GetCell(j);

としてますがその直前のコードで

C#

1for (int j = 4; j < row.Cells.Count; j++) {

のようにrow.Cellsを使用してますので本当にrowがnullの場合、row?.GetCellを使用する前のrow.CellsでNullReferenceExceptionが発生するはずです
なのでrow?.GetCellの「?」は意味がありません。

3.cellの値取得

CellType.StringとCellType.Numericの時しか値を使用しないのであればCellType.Blankのケースはdefault側で処理したほうがシンプルだと思います。

4.datalistsの型

C#

1//1行のセルをすべて取り終わったあとにstringの値をstring[]に変換し、格納 2datalists.Add(sv.ToArray());

としてますが掲示してあるソースから配列とコレクションの使い分けが出来てるとは思えません。
わざわざ配列に変換しなくてもList<string>のまま入れてしまったほうが簡単です。
なのでdatalistsの型は

C#

1List<List<string>> datalists = new List<List<string>>();

でいいと思います。
※この点は本来のソースの状況次第で考えは変わると思います。

5.シート2を閉じる/ブックを閉じる

C#

1//シート2を閉じる 2workbook.CloneSheet(1); 3workbook.Close();

「シート2を閉じる」となってますが前者のメソッド(CloneSheet)はクローン(複製)処理ですよ?

6.変数名

もう少し.NETの名前付けのガイドラインを読まれたほうがいいと思います。
名前付けのガイドライン

7.シートの取り扱い

C#

1workbook.GetSheetAt(1)

C#

1workbook.CloneSheet(1);

のようにシート位置で参照してますがシート名でアクセスするほうがいいのではと思ってます。
シートの位置よりシート名のほうが変更されにくいのかなとは思いますがシート名が不明ということであればシート位置で参照するというのは仕方がないと思います。

その他

それ以外にSurferOnWwwさんの言われるように質問に対して反応してくださった方がおられたらちゃんと返信すべきだと思います。
今回の内容であればかなり簡単な内容なので回答は付きやすいはずですが今までの経緯等で回答が付きにくくなってると思いますよ。

また、今回の質問であればSubItemsを使用した場合のほうや対象としてるエクセルのサンプルイメージを掲示してくれてたらもう少し違ったと思います。

さらに、
C# NPOIを使用時、エクセルファイルの値が空のときのエラーについて
epistemeさんが解決策をくれてるのに今回のソースでそれが生かされていません。

ということで小言はこのぐらいに私なら下記のような感じでコーディングします。

※前提条件として取得する行は8行目と9行目のみを取得として処理してます。ほかの行も同様に取得するのであれば、修正が必要です
また、元となるエクセルやリストビューにどのように表示したいかが言葉だけで説明されてるので勘違いはあるかもしれません。
(イメージとしてはエクセルのペースト機能の一部の「行/列の入れ替え」をしたいのかなと予想してます)

C#

1public Form1() { 2 InitializeComponent(); 3 4 listView1.Columns.Add("項目1"); 5 listView1.Columns.Add("項目2"); 6 listView1.View = View.Details; 7 8 SetItems(); 9} 10 11private void SetItems() { 12 13 // エクセルファイルを開く 14 var workbook = WorkbookFactory.Create(@"test.xlsx"); 15 16 // 対象シートを取得 17 var worksheet = workbook.GetSheet("シート2"); 18 19 var items = new List<ListViewItem>(); 20 21 var row1 = worksheet.GetRow(8); 22 var row2 = worksheet.GetRow(9); 23 24 // 1行目のセルの数を列数として扱う 25 var cellCount = row1?.Cells.Count ?? 0; 26 27 for (var i = 4; i < cellCount; i++) { 28 29 var cells = new[] { row1.GetCell(i), row2.GetCell(i) }; 30 var values = new string[] { "", "" }; 31 32 // 1行目と2行目のセルの値を格納 33 for (var j = 0; j < 2; j++) { 34 35 var cell = cells[j]; 36 37 //セルの型に応じたプロパティを参照する 38 switch (cell?.CellType ?? CellType.Unknown) { 39 //セルの型がstringのとき 40 case CellType.String: 41 values[j] = cell.StringCellValue; 42 break; 43 //セルの型が数値のとき 44 case CellType.Numeric: 45 values[j] = Convert.ToString(cell.NumericCellValue); 46 break; 47 default: 48 //空を代入 49 values[j] = ""; 50 break; 51 } 52 53 } 54 55 // リストビューアイテムを作成 56 items.Add(new ListViewItem(values)); 57 } 58 59 // ブックを閉じる 60 workbook.Close(); 61 62 // リストビューをクリアして項目を一括追加 63 listView1.SuspendLayout(); 64 listView1.Items.Clear(); 65 listView1.Items.AddRange(items.ToArray()); 66 listView1.ResumeLayout(); 67 68}

投稿2022/06/15 03:23

dekaaki

総合スコア292

sueteacher👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

sueteacher

2022/06/16 06:47

イメージ通りで動きました。ありがとうございます。

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

ただいまの回答率
86.02%

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

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

質問する

関連した質問

同じタグがついた質問を見る

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番目のメジャーバージョンです。