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

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

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

Open XMLは、マイクロソフト社が開発したオープンなXMLベースのオフィススイート用のファイル形式です。従来のバイナリ形式のフォーマットに代わって、XMLを用いた規格を標準ファイル形式として採用しています。

Open XML SDK

Open XML SDKは、Office2007から採用されているドキュメントファイルフォーマット。オープンソースとしてGitHubで公開されています。Office Open XMLファイルを作成したり編集することが可能です。

Q&A

解決済

1回答

4738閲覧

[openXML]RelationshipIDが存在しない

shikasama

総合スコア163

Open XML

Open XMLは、マイクロソフト社が開発したオープンなXMLベースのオフィススイート用のファイル形式です。従来のバイナリ形式のフォーマットに代わって、XMLを用いた規格を標準ファイル形式として採用しています。

Open XML SDK

Open XML SDKは、Office2007から採用されているドキュメントファイルフォーマット。オープンソースとしてGitHubで公開されています。Office Open XMLファイルを作成したり編集することが可能です。

0グッド

0クリップ

投稿2016/09/07 09:38

編集2016/11/10 13:47

openXMLでシートをコピーしたExcelファイルをOpenXmlSdkToolで見てみると

The relationship 'Rbc3d40956dac4fb9' referenced by attribute 'http://schemas.openxmlformats.org/officeDocument/2006/realationships:id' does not exist.

というエラーが発生しました。

workbook.xml.relsを見てみると

<?xml version="1.0" encoding="UTF-8" standalone="true"?> -<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> <Relationship Target="styles.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Id="rId3"/> <Relationship Target="theme/theme1.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Id="rId2"/> <Relationship Target="worksheets/sheet1.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Id="rId1"/> <Relationship Target="calcChain.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/calcChain" Id="rId5"/> <Relationship Target="sharedStrings.xml" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" Id="rId4"/> </Relationships>

追加したはずのシートがありませんでした。
xl\worksheetsの方には2つ目のシートはありました。

以下のサイトを参考にしました。
How to Copy a Worksheet within a Workbook
コードは以下の通りです。

C#

1private static void CopySheet(WorkbookPart workBookPart, string sheetName, string clonedSheetName) 2{ 3 // コピー対象のワークシートを取得 4 WorksheetPart sourceSheetPart = GetWorkSheetPart(workBookPart, sheetName); 5 6 // 一時ドキュメント取得 7 using (SpreadsheetDocument tempSpreadSheet = SpreadsheetDocument.Create(new MemoryStream(), SpreadsheetDocumentType.Workbook)) 8 { 9 // WorkbookPartのコピー 10 WorkbookPart tempWorkBookPart = tempSpreadSheet.AddWorkbookPart(); 11 12 WorksheetPart tempWorkSheetPart = tempWorkBookPart.AddPart<WorksheetPart>(sourceSheetPart); 13 14 WorksheetPart clonedSheet = workBookPart.AddPart<WorksheetPart>(tempWorkSheetPart); 15 16 // テーブルID作成 17 int numTableDefParts = sourceSheetPart.GetPartsCountOfType<TableDefinitionPart>(); 18 19 tableId = numTableDefParts; 20 21 if (numTableDefParts != 0) 22 { 23 // テーブル定義のクリーンアップ 24 FixupTableParts(clonedSheet, numTableDefParts); 25 } 26 27 // フォーカスが当たってるシートが1つのみ存在するのでクリーン 28 CleanView(clonedSheet); 29 30 // シートのコピー 31 Sheets sheets = workBookPart.Workbook.GetFirstChild<Sheets>(); 32 33 Sheet copiedSheet = new Sheet(); 34 35 copiedSheet.Name = clonedSheetName; 36 37 copiedSheet.Id = workBookPart.GetIdOfPart(clonedSheet); 38 39 copiedSheet.SheetId = workBookPart.Workbook.Descendants<Sheet>().LastOrDefault().SheetId + 1; 40 41 sheets.Append(copiedSheet); 42 43 workBookPart.Workbook.Save(); 44 } 45}

ご教示おねがいします。

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

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

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

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

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

guest

回答1

0

自己解決

CopySheetの呼出元がいけなかったようです。

C#

1public byte[] MakeXlsx() 2{ 3 var templateName = HostingEnvironment.MapPath("~/App_Data/Template.xlsx"); 4 5 var byteArray = System.IO.File.ReadAllBytes(templateName); 6 using (MemoryStream ms = new MemoryStream()) 7 { 8 ms.Write(byteArray, 0, (int)byteArray.Length); 9 using (SpreadsheetDocument spreadSheet = SpreadsheetDocument.Open(ms, true)) 10 { 11 WorkbookPart wbPart = spreadSheet.WorkbookPart; 12 13 CopySheet(wbPart, "シート1", "シート2"); 14 15 return ms.ToArray(); 16 } 17 } 18}

としていたのですがどうやら

C#

1return ms.ToArray();

の位置が悪かったらしく

C#

1public byte[] MakeXlsx() 2{ 3 var templateName = HostingEnvironment.MapPath("~/App_Data/Template.xlsx"); 4 5 var byteArray = System.IO.File.ReadAllBytes(templateName); 6 using (MemoryStream ms = new MemoryStream()) 7 { 8 ms.Write(byteArray, 0, (int)byteArray.Length); 9 using (SpreadsheetDocument spreadSheet = SpreadsheetDocument.Open(ms, true)) 10 { 11 WorkbookPart wbPart = spreadSheet.WorkbookPart; 12 13 CopySheet(wbPart, "シート1", "シート2"); 14 } 15 return ms.ToArray(); 16 } 17}

としたら解決しました。

投稿2016/09/08 04:47

shikasama

総合スコア163

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

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

twck

2016/09/08 06:34

呼出元がいけなかったそうなので必要ないと思いますが、XMLを使った複写の方法を見つけたので載せておきます。 // 複写元の取得 WorksheetPart sourceSheetPart = GetWorkSheetPart(workBookPart, sheetName); // 複写 var clonedSheet = workBookPart.AddNewPart<WorksheetPart>(); clonedSheet.Worksheet = new Worksheet(sourceSheetPart.Worksheet.OuterXml); // 複写先の新しいシートの情報をブックに追加する Sheet copiedSheet = new Sheet(); copiedSheet.Name = clonedSheetName; copiedSheet.Id = workBookPart.GetIdOfPart(clonedSheet); copiedSheet.SheetId = workBookPart.Workbook.Descendants<Sheet>().LastOrDefault().SheetId + 1; workBookPart.Workbook.Sheets.Append(copiedSheet); それにしても Open XML は難しい。 NPOI でできない事を Open XML でやろうと思ってたけど学習コストが高すぎる・・・
shikasama

2016/09/08 09:06

twck様 回答ありがとうございます。 そっちの方がスマートですね。参考にさせていただきます。 NPOIやClosedXMLなど使ったことがなくていきなりOpen XMLでした。 サンプルも少なくてOpen XML難しいです…。 Excelをいじるのがこんなにも大変だとは思っていなかったです。 一段落ついたらNPOIやClosedXMLを勉強してみようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問