Установить область печати - OpenXML с Excel - PullRequest
2 голосов
/ 06 декабря 2011

Кто-нибудь знает, как установить область печати через OpenXML SDK в Excel?

Я пытался использовать следующий код:

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);

    }
}

UPDATE:

Я продолжаю получать сообщение об ошибке от 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)

Ответы [ 2 ]

2 голосов
/ 06 декабря 2011

Я нашел некоторую информацию о методе, который, похоже, не использует Interop. Вы можете попробовать что-то вроде:

//load the work book
...

myWorkBook.Worksheets.First().PageSetup.PrintAreas.Add("A1:F40");

//save the workbook
//...

Посмотрите, поможет ли это. Я сам еще не пробовал, но собираюсь проверить это.

UPDATE: Первый метод, кажется, требует дополнительной библиотеки. Вы можете получить это здесь: 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";.

Вы должны изменить значение Text, чтобы оно содержало информацию в формате: [имя рабочего листа]! [Левый верхний угол области печати]: [правый нижний угол области печати] . Он должен установить вашу область печати в прямоугольник с верхним левым и нижним правым углами, как указано.

Если вы хотите указать области печати для разных листов, попробуйте добавить несколько 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 голос
/ 29 января 2016

Позвольте мне объяснить мой случай: у меня есть книга Excel со следующими листами (T1, I1, M1). Теперь мое требование было основано на некотором условии 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. Текст имеет формат 'T1'! $ A $ 1: $ AG $ 19

printAreaDefName.Text = "'" + copiedSheet.Name + "'!$A$1:$AG$22";

workbookPart.Workbook.DefinedNames.Append(printAreaDefName); 
workbookPart.Workbook.Save();

Мне не нужно было добавлять новое Definedname в коллекцию DefinedNames. Поэтому я просто добавил в книгу определенную коллекцию имен, и она сработала.

...