OpenXML Pagesetup(PrintOptions、pageMargins、Orientation、headerfooter)错误
OpenXML Pagesetup (PrintOptions, pageMargins, Orientation, headerfooter) Error
我有一个生成格式化 Excel 报告的 c# 程序。由于Office升级,我将程序转换为使用Microsoft Excel 16 Object Library。除了页面设置 class 之外,一切都很好。新 DLL 不再支持页面设置 class。由于报告的代码量很大,我决定用 OpenXML 修改最后的 Excel 文件。
我研究了原来的OpenXML,把文件的后缀改为zip。下面是对应于页面设置的原始 OpenXML class.
<printOptions horizontalCentered="1"/>
<pageMargins left="0.5" right="0.5" top="0.75" bottom="0.75" header="0.3" footer="0.3"/>
<pageSetup orientation="landscape" r:id="rId1"/>
<headerFooter><oddHeader>&L&"Arial Narrow,Bold"&8 9825 Fairmount Drive SE
&R&"Arial Narrow,Bold"&8Ref. No.: 10-219</oddHeader>
<oddFooter>&C&"Arial Narrow,Regular"&8Page 1 of 2</oddFooter></headerFooter>
<headerFooter>
<oddHeader>&R&8&B&"Arial Narrow"Ref. No.: 10-219
&L&8&B&"Arial Narrow"9825 Fairmount Drive SE</oddHeader>
<oddFooter>&C&8&"Arial Narrow"Page 2 of 2</oddFooter></headerFooter>
但是,在我用OpenXML函数格式化Excel文件后,Excel告诉我文件中有OpenXML代码错误。以下是修改后文件的摘录:
<x:pageMargins left="0.5" right="0.5" top="0.75" bottom="0.75" header="0.3" footer="0.3" />
<x:printOptions horizontalCentered="1" />
<x:pageSetup orientation="landscape" />
<x:headerFooter differentOddEven="0">
<x:oddHeader>&L&B&"Arial Narrow"&9825 Fairmount Drive SE&R&B&"Arial Narrow"&8Ref. No.: 10-219</x:oddHeader>
<x:oddFooter>&C&"Arial Narrow"&8Page &P of &N</x:oddFooter></x:headerFooter>
似乎在每个标签的开头放了一个 x: 和 /x:。下面是我的 OpenXML 函数。
public void formatLandscapeReport(String fileName, String jobNumber, String Address) {
using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileName, true))
{
WorkbookPart workbookpart = document.WorkbookPart;
IEnumerable<String> worksheetIds = workbookpart.Workbook.Descendants<Sheet>().Select(w => w.Id.Value);
WorksheetPart worksheetpart = null;
foreach (String worksheetId in worksheetIds)
{
worksheetpart = ((WorksheetPart)workbookpart.GetPartById(worksheetId));
PrintOptions po = new PrintOptions();
po.HorizontalCentered = true;
worksheetpart.Worksheet.AppendChild(po);
PageMargins pm = worksheetpart.Worksheet.Descendants<PageMargins>().FirstOrDefault();
if (pm == null)
{
pm = new PageMargins();
worksheetpart.Worksheet.AppendChild(pm);
}
pm.Left = .5D;
pm.Right = .5D;
pm.Top = .75D;
pm.Bottom = .75D;
PageSetup pagesetup = worksheetpart.Worksheet.Descendants<PageSetup>().FirstOrDefault();
if (pagesetup == null)
{
pagesetup = new PageSetup();
worksheetpart.Worksheet.AppendChild(pagesetup);
}
pagesetup.Orientation = OrientationValues.Landscape;
// Header and Footer
HeaderFooter hf = new HeaderFooter();
hf.DifferentOddEven = false;
OddHeader ohdr = new OddHeader();
OddFooter oftr = new OddFooter();
ohdr.Text= "&L&B&\"Arial Narrow\"&" + Address +"&R&B&\"Arial Narrow\"&8Ref. No.: " + jobNumber;
oftr.Text = "&C&\"Arial Narrow\"&8Page &P of &N";
hf.Append(ohdr);
hf.Append(oftr);
worksheetpart.Worksheet.Append(hf);
worksheetpart.Worksheet.Save();
} // foreach
workbookpart.Workbook.Save();
} // using
} //formatLandscapeReport
如果有人能告诉我我做错了什么,将不胜感激。
谢谢,
卡门
ECMA 架构的相关部分是这样的:
<xsd:sequence>
...
<xsd:element name="printOptions" type="CT_PrintOptions" minOccurs="0" maxOccurs="1"/>
<xsd:element name="pageMargins" type="CT_PageMargins" minOccurs="0" maxOccurs="1"/>
<xsd:element name="pageSetup" type="CT_PageSetup" minOccurs="0" maxOccurs="1"/>
<xsd:element name="headerFooter" type="CT_HeaderFooter" minOccurs="0" maxOccurs="1"/>
....
<xsd:sequence>
请注意,此构造定义为 sequence
,因此顺序很重要。
在您的原始文件中,printOptions
出现在 之前 pageMargins
的顺序是正确的,但在您不正确的文件中,顺序是错误的。
调换顺序应该可以解决您的问题,因此问题会变成 "why is the order wrong?"。
问题很可能是您的 Worksheet
已经包含一个 PageMargins
项,因此 PrintOptions
是在它们之后添加的。
要解决这个问题,你总是可以先做PageMargins
代码,然后使用InsertBefore
方法在PageMargins
之前插入PrintOptions
:
PageMargins pm = worksheetpart.Worksheet.Descendants<PageMargins>().FirstOrDefault();
if (pm == null)
{
pm = new PageMargins();
worksheetpart.Worksheet.AppendChild(pm);
}
pm.Left = .5D;
pm.Right = .5D;
pm.Top = .75D;
pm.Bottom = .75D;
worksheetpart = ((WorksheetPart)workbookpart.GetPartById(worksheetId));
PrintOptions po = new PrintOptions();
po.HorizontalCentered = true;
//the PrintOptions must be before the PageMargins
worksheetpart.Worksheet.InsertAfter(po, pm);
x:
部分只是一个命名空间。我不认为那会是你的问题的原因。
我有一个生成格式化 Excel 报告的 c# 程序。由于Office升级,我将程序转换为使用Microsoft Excel 16 Object Library。除了页面设置 class 之外,一切都很好。新 DLL 不再支持页面设置 class。由于报告的代码量很大,我决定用 OpenXML 修改最后的 Excel 文件。
我研究了原来的OpenXML,把文件的后缀改为zip。下面是对应于页面设置的原始 OpenXML class.
<printOptions horizontalCentered="1"/>
<pageMargins left="0.5" right="0.5" top="0.75" bottom="0.75" header="0.3" footer="0.3"/>
<pageSetup orientation="landscape" r:id="rId1"/>
<headerFooter><oddHeader>&L&"Arial Narrow,Bold"&8 9825 Fairmount Drive SE
&R&"Arial Narrow,Bold"&8Ref. No.: 10-219</oddHeader>
<oddFooter>&C&"Arial Narrow,Regular"&8Page 1 of 2</oddFooter></headerFooter>
<headerFooter>
<oddHeader>&R&8&B&"Arial Narrow"Ref. No.: 10-219
&L&8&B&"Arial Narrow"9825 Fairmount Drive SE</oddHeader>
<oddFooter>&C&8&"Arial Narrow"Page 2 of 2</oddFooter></headerFooter>
但是,在我用OpenXML函数格式化Excel文件后,Excel告诉我文件中有OpenXML代码错误。以下是修改后文件的摘录:
<x:pageMargins left="0.5" right="0.5" top="0.75" bottom="0.75" header="0.3" footer="0.3" />
<x:printOptions horizontalCentered="1" />
<x:pageSetup orientation="landscape" />
<x:headerFooter differentOddEven="0">
<x:oddHeader>&L&B&"Arial Narrow"&9825 Fairmount Drive SE&R&B&"Arial Narrow"&8Ref. No.: 10-219</x:oddHeader>
<x:oddFooter>&C&"Arial Narrow"&8Page &P of &N</x:oddFooter></x:headerFooter>
似乎在每个标签的开头放了一个 x: 和 /x:。下面是我的 OpenXML 函数。
public void formatLandscapeReport(String fileName, String jobNumber, String Address) {
using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileName, true))
{
WorkbookPart workbookpart = document.WorkbookPart;
IEnumerable<String> worksheetIds = workbookpart.Workbook.Descendants<Sheet>().Select(w => w.Id.Value);
WorksheetPart worksheetpart = null;
foreach (String worksheetId in worksheetIds)
{
worksheetpart = ((WorksheetPart)workbookpart.GetPartById(worksheetId));
PrintOptions po = new PrintOptions();
po.HorizontalCentered = true;
worksheetpart.Worksheet.AppendChild(po);
PageMargins pm = worksheetpart.Worksheet.Descendants<PageMargins>().FirstOrDefault();
if (pm == null)
{
pm = new PageMargins();
worksheetpart.Worksheet.AppendChild(pm);
}
pm.Left = .5D;
pm.Right = .5D;
pm.Top = .75D;
pm.Bottom = .75D;
PageSetup pagesetup = worksheetpart.Worksheet.Descendants<PageSetup>().FirstOrDefault();
if (pagesetup == null)
{
pagesetup = new PageSetup();
worksheetpart.Worksheet.AppendChild(pagesetup);
}
pagesetup.Orientation = OrientationValues.Landscape;
// Header and Footer
HeaderFooter hf = new HeaderFooter();
hf.DifferentOddEven = false;
OddHeader ohdr = new OddHeader();
OddFooter oftr = new OddFooter();
ohdr.Text= "&L&B&\"Arial Narrow\"&" + Address +"&R&B&\"Arial Narrow\"&8Ref. No.: " + jobNumber;
oftr.Text = "&C&\"Arial Narrow\"&8Page &P of &N";
hf.Append(ohdr);
hf.Append(oftr);
worksheetpart.Worksheet.Append(hf);
worksheetpart.Worksheet.Save();
} // foreach
workbookpart.Workbook.Save();
} // using
} //formatLandscapeReport
如果有人能告诉我我做错了什么,将不胜感激。
谢谢,
卡门
ECMA 架构的相关部分是这样的:
<xsd:sequence>
...
<xsd:element name="printOptions" type="CT_PrintOptions" minOccurs="0" maxOccurs="1"/>
<xsd:element name="pageMargins" type="CT_PageMargins" minOccurs="0" maxOccurs="1"/>
<xsd:element name="pageSetup" type="CT_PageSetup" minOccurs="0" maxOccurs="1"/>
<xsd:element name="headerFooter" type="CT_HeaderFooter" minOccurs="0" maxOccurs="1"/>
....
<xsd:sequence>
请注意,此构造定义为 sequence
,因此顺序很重要。
在您的原始文件中,printOptions
出现在 之前 pageMargins
的顺序是正确的,但在您不正确的文件中,顺序是错误的。
调换顺序应该可以解决您的问题,因此问题会变成 "why is the order wrong?"。
问题很可能是您的 Worksheet
已经包含一个 PageMargins
项,因此 PrintOptions
是在它们之后添加的。
要解决这个问题,你总是可以先做PageMargins
代码,然后使用InsertBefore
方法在PageMargins
之前插入PrintOptions
:
PageMargins pm = worksheetpart.Worksheet.Descendants<PageMargins>().FirstOrDefault();
if (pm == null)
{
pm = new PageMargins();
worksheetpart.Worksheet.AppendChild(pm);
}
pm.Left = .5D;
pm.Right = .5D;
pm.Top = .75D;
pm.Bottom = .75D;
worksheetpart = ((WorksheetPart)workbookpart.GetPartById(worksheetId));
PrintOptions po = new PrintOptions();
po.HorizontalCentered = true;
//the PrintOptions must be before the PageMargins
worksheetpart.Worksheet.InsertAfter(po, pm);
x:
部分只是一个命名空间。我不认为那会是你的问题的原因。