有人知道如何在Excel中通过OpenXML SDK设置打印区域吗?
我尝试使用以下代码:
public void XLUpdateDefinedName(string fileName, string definedName, string newRange)
{
using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileName, true))
{
WorkbookPart wbPart = document.WorkbookPart;
var definedNames = wbPart.Workbook.Descendants<DefinedNames>().FirstOrDefault();
DefinedName name = definedNames.Descendants<DefinedName>().Where(m => m.Name == definedName).Single();
UInt32Value locSheetId = name.LocalSheetId;
name = null;//.Remove();
wbPart.Workbook.Save();
name = new DefinedName() { Name = definedName, LocalSheetId = locSheetId , Text = newRange}
;
wbPart.Workbook.Save();
//newDefinedName.Text = newRange;
//definedNames.Append(newDefinedName);
}
}
更新
我继续收到excel的错误,说明文件中包含以下代码的内容不可读。
public void XLUpdateDefinedName(string fileName, string definedName, string newRange, string sheet, UInt32Value localId)
{
using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileName, true))
{
String sheetName = sheet;
string topLeft = newRange.Split(':').First();
string bottomRight = newRange.Split(':').Last();
WorkbookPart wbPart = document.WorkbookPart;
var definedNames = wbPart.Workbook.Descendants<DefinedNames>().FirstOrDefault();
var nameCollection = definedNames.Descendants<DefinedName>().Where(m => m.Text.StartsWith(sheetName));
DefinedName name = nameCollection.Count() > 0 ? nameCollection.First() : null;
UInt32Value locSheetId;
if (name != null)
{
locSheetId = name.LocalSheetId;
name.Remove();
wbPart.Workbook.Save();
}
else
{
locSheetId = localId;
}
name = new DefinedName() { Name = "_xlnm.Print_Area", LocalSheetId = locSheetId};
name.Text = String.Format("{0}!{1}:{2}", sheetName,topLeft,bottomRight);
definedNames.Append(name);
wbPart.Workbook.Save();
}}
newRange的形式($ A $ 10:$ C $ 15)
答案 0 :(得分:2)
我找到了一些似乎没有使用Interop的方法的信息。您可以尝试以下方式:
//load the work book
...
myWorkBook.Worksheets.First().PageSetup.PrintAreas.Add("A1:F40");
//save the workbook
//...
看看这是否有帮助。我还没有尝试过,但我要验证它。
<强>更新强> 第一种方法似乎需要一个额外的库。你可以从这里得到它: http://closedxml.codeplex.com/。我自己没有用过它,所以我无法向你保证它是否正常工作。
纯OpenXML解决方案
我设法通过在记事本编辑器中手动修改xlsx文件内容来更改打印区域。
在C#中你应该尝试使用以下方法(它将打印区域设置为 A1:G19 ):
//first you need to get reference to your workbook, but I assume you already have this
//...
//then you can add an information about desired print area
DefinedNames definedNames = new DefinedNames();
DefinedName printAreaDefName = new DefinedName() { Name = "_xlnm.Print_Area", LocalSheetId = (UInt32Value)0U };
printAreaDefName.Text = "Worksheet1!$A$1:$G$19";
definedNames.Append(printAreaDefName);
//then you should append the created element to your workbook
//...
workbook1.Append(definedNames);
您需要更改的内容是行:printAreaDefName.Text = "Worksheet1!$A$1:$G$19";
。
您应更改文本值以包含以下格式的信息: [工作表名称]![打印区域的左上角]:[打印区域的右下角] 。它应该将您的打印区域设置为一个矩形,其中包含指定的左上角和右下角。
如果要为不同的工作表指定打印区域,请尝试添加多个DefinedName
个对象:
DefinedName printAreaDefName = new DefinedName() { Name = "_xlnm.Print_Area", LocalSheetId = (UInt32Value)0U };
printAreaDefName.Text = "Worksheet1!$A$1:$G$19";
definedNames.Append(printAreaDefName);
DefinedName printAreaDefName2 = new DefinedName() { Name = "_xlnm.Print_Area", LocalSheetId = (UInt32Value)1U };
printAreaDefName2.Text = "Worksheet2!$B$1:$H$23";
definedNames.Append(printAreaDefName2);
DefinedName printAreaDefName3 = new DefinedName() { Name = "_xlnm.Print_Area", LocalSheetId = (UInt32Value)2U };
printAreaDefName3.Text = "Worksheet3!$A$1:$J$10";
definedNames.Append(printAreaDefName3);
我还建议使用 OpenXML SDK 2.0生产力工具。它允许您显示所选OpenXML文件的内容,比较文件,验证文件,甚至显示您要编写的C#代码,以便以编程方式重新创建文件:)。 你可以在这里下载: http://www.microsoft.com/download/en/details.aspx?id=5124
更新II:
我更正了打印区域值字符串格式的错误。对困惑感到抱歉。 我还采用了您发布的代码并基于它创建了一个方法。它工作正常,修改打印区域后,我可以在Excel中打开文件,没有问题。该代码假定已经定义了打印范围,您现在只是更改它,但也可以修改它以添加新的打印范围。 这是代码:
private void OpenXmlFileHandling(String fileName)
{
using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileName, true))
{
//some sample values
String definedName = "Worksheet3";
String topLeft = "$A$3";
String bottomRight = "$D$7";
WorkbookPart wbPart = document.WorkbookPart;
var definedNames = wbPart.Workbook.Descendants<DefinedNames>().FirstOrDefault();
var namesCollection = definedNames.Descendants<DefinedName>().Where(m => m.Text.StartsWith(definedName));
DefinedName name = namesCollection != null ? namesCollection.First() : null;
UInt32Value locSheetId;
//we assume that name is not null, because print range for this worksheet was defined in the source template file
//if name was null, we should probably just assign to locSheetId a number definedNames.Count() + 1 and not remove the name node
locSheetId = name.LocalSheetId;
name.Remove();
wbPart.Workbook.Save();
name = new DefinedName() { Name = "_xlnm.Print_Area", LocalSheetId = locSheetId, Text = String.Format("{0}!{1}:{2}", definedName, topLeft, bottomRight) };
definedNames.Append(name);
wbPart.Workbook.Save();
}
}
我将工作表名称和打印区域范围的值放在方法中,这样您就可以看到它们应该具有哪种值。我希望这会有所帮助。
答案 1 :(得分:1)
让我解释一下我的情况:我有以下表格(T1,I1,M1)的excel工作簿。现在我的要求是基于某些条件T1,I1,M1将多次复制到同一个excel工作簿,例如T2,I2,M2,T3,I3,M3等。对我来说,I2,M2对打印区域没有任何问题,但对于复制的纸张T2,T3 ......有问题。因为它有庞大的数据。 excel列上升到“AG”。所以这就是我在代码中做的事情
将新工作表添加到工作簿
sheets.Append(copiedSheet);
首先获取当前的工作表计数
var count = sheets.Count();
获取工作表计数,这将在LocalsheetId中用作printarea设置。
仅对于复制的技术表单,打印区域设置不正确。因此需要正确设置。
DefinedName printAreaDefName = new DefinedName() { Name = "_xlnm.Print_Area", LocalSheetId = Convert.ToUInt32(count) };
请注意defName.Text,格式为'T1'!$ A $ 1:$ AG $ 19
printAreaDefName.Text = "'" + copiedSheet.Name + "'!$A$1:$AG$22";
workbookPart.Workbook.DefinedNames.Append(printAreaDefName);
workbookPart.Workbook.Save();
我无需在DefinedNames集合中添加新的Definedname。所以我刚刚添加到工作簿的definedNames集合中,并且工作正常。