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

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

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

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

Windows Forms

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

Q&A

解決済

2回答

14519閲覧

C# NPOIを使ったWorkbookFactory.Createでのエラー

tatenisi

総合スコア13

C#

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

Windows Forms

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

0グッド

0クリップ

投稿2019/01/31 08:05

前提・実現したいこと

NPOIを使ってエクセル内のシート名を読み込もうとしています。
拡張子がxls形式(excel97-2003)では出来ることが、xlsx形式になると出来なくなります。

発生している問題・エラーメッセージ

エラーメッセージ
A part with the name 'xl/styles.xlm' already exsits : Packages shall not contain equivalent part names and package implementers shall neither create nor recognize packages with equivalent part names.[M1.12]

該当のソースコード

C#ここに言語名を入力

private void picAddExcelFile_Click(object sender, EventArgs e) //Excelファイルマークから読込 { try { OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Filter = "Excelファイル|*.xlsx;*.xlsm;*.xls"; //読込可能な拡張子の設定 openFileDialog.Title = "Excelファイルをリストに追加"; openFileDialog.Multiselect = true; if (openFileDialog.ShowDialog() != DialogResult.OK) //ここでファイルオープンウィンドウを表示 return; this.dgvExcelList.ClearSelection(); foreach (string fileName in openFileDialog.FileNames) //ファイル名をfileNameに読込 { if (File.Exists(fileName)) //ファイルが存在するか確認 { bool flag = false; foreach (DataGridViewRow row in (IEnumerable)this.dgvExcelList.Rows) { if (string.Compare(fileName, (string)row.Cells["clmFilePath"].Value, true) == 0) { flag = true; break; } } if (!flag) { Dictionary<string, int> sheetNameList = new ExcelNpoi().GetSheetNameList(fileName); //ここでGetSheetNameList();呼び出し int index = this.dgvExcelList.Rows.Add(); this.dgvExcelList.Rows[index].Cells["clmFileName"].Value = (object)Path.GetFileName(fileName); this.dgvExcelList.Rows[index].Cells["clmSheetName"].Value = (object)string.Join(",", sheetNameList.Keys.ToArray<string>()); this.dgvExcelList.Rows[index].Cells["clmFilePath"].Value = (object)fileName; this.dgvExcelList.Rows[index].Selected = true; } } } } catch (Exception ex) { int num = (int)MessageBox.Show(ex.Message); } } **これは厳密には別のクラスで宣言してます** public Dictionary<string, int> GetSheetNameList(string filePath) //エクセル内のシート名を返す { using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { IWorkbook workbook = WorkbookFactory.Create((Stream) fileStream, ImportOption.TextOnly); int numberOfSheets = workbook.NumberOfSheets; Dictionary<string, int> dictionary = new Dictionary<string, int>((IEqualityComparer<string>) StringComparer.OrdinalIgnoreCase); for (int index = 0; index < numberOfSheets; ++index) { ISheet sheetAt = workbook.GetSheetAt(index); dictionary.Add(sheetAt.SheetName, index); } return dictionary; } }

試したこと

xlsファイルの場合は、GetSheetNameList();が正常に動作し、以降の処理も問題なく動きます。
xlsxファイルの場合は、WorkbookFactory.Create();実行後、picAddExcelFile_Click();のtry内のcatch (Exception ex)に引っかかり、上記のエラーメッセージが表示されます。

補足情報(FW/ツールのバージョンなど)

もういなくなってしまった人のプログラムで、社内に聞ける人がいないので投稿します。
エラー文を調べる限り、string.Compare();の関係エラーだと思うのですが、WorkbookFactory.Create();内で何が起きてるのかが分からず、
エラーの内容も調べてみましたが分かりません。
よろしくお願いします。

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

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

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

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

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

guest

回答2

0

ベストアンサー

xlsxの場合でもxlsの場合でもCreateできるのがWorkbookFactoryなんですが、どうもこの第2引数、ImportOptionはxlsの場合しか使えないように思います(実際の検証&推測)。

実際、第2引数を取り払うとエラーは消えるのではないでしょうか?

csharp

1IWorkbook workbook = WorkbookFactory.Create((Stream)fileStream,ImportOption.); 2//IWorkbook workbook = WorkbookFactory.Create((Stream)fileStream, ImportOption.TextOnly);

なんで使えないと思ったかというと、GitHubのNPOIに関するソースで、第2引数に関して「XSSF形式(NPOIでのxls形式のファイルを扱うときのタイプ)でしか使えない」というコメントがあるからです。

npoi/ooxml/SS/UserModel/WorkbookFactory.cs

第2引数は、上記リンク先のソースの中、「SetImportOption」というメソッドで処理されるのですが、そこでコメント部分に下記の記述があります。

csharp

1 /// <summary> 2 /// Sets the import option when opening the next workbook. 3 /// Works only for XSSF. For HSSF workbooks this option is ignored. 4 /// </summary> 5 /// <param name="importOption">Customize the elements that are processed on the next import</param> 6 public static void SetImportOption(ImportOption importOption) 7 { 8 if (ImportOption.SheetContentOnly == importOption) 9 {

「XSSFの場合だけ動作し、HSSF(xlsx形式)の場合は無視される」。コメント通りなら無視されるようですが……エラーになりますね。とりあえず、根本原因はよく分かりませんが、TextOnlyの指定を取り払っても動作に問題無いようであれば、取っ払ってもいいのではないでしょうか?

投稿2019/01/31 08:58

backyard

総合スコア534

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

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

tatenisi

2019/02/04 04:26

返事が遅くなり申し訳ありません。 ご指摘の通り、Importoption.TextOnlyを取り除いたらxlsx形式のファイルでも問題なく読み込めて、動作も正常に行われました! 調べてもNPOIはxls,xlsxどっちでも使えると書いてあるのにどうして…と思っていたのですが、こんなところに問題があったとは… ありがとうございました!
guest

0

「.xlsx」の場合はXSSFで、「.xls」はHSSFになるので、

IWorkbook workbook = WorkbookFactory.Create((Stream) fileStream, ImportOption.TextOnly);

上記でworkbookに渡すときに拡張子の形式で判定するようにしてください。

投稿2019/01/31 08:42

pontaq

総合スコア31

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問