Импорт файла Excel со всеми правилами условного форматирования в epplus

У меня есть файл Excel, который содержит много данных, а также наборы значков и панели данных на основе значений в ячейке. Это выглядит так:

Я хочу импортировать этот лист Excel вместе с условным форматированием. Есть ли библиотека для этого? Я прошел этот http://www.sitecorecleveland.com/resources/blogs-posts/easy_excel_interaction_pt6 но он импортирует только данные, а не формат.

Если это невозможно, есть ли в epplus код для добавления этих наборов значков в таблицу Excel. Я могу иметь стрелки, светофоры и т. Д., Но не эти.

1 ответ

Решение

Я не думаю, что EPP поддерживает пользовательское условное форматирование, которое хранится как "Расширения рабочей книги" в XML-файле Excel. Вы можете скопировать узел xml "extLst", который содержит пользовательское форматирование, с одного рабочего листа на другой. Просто убедитесь, что кроме XML-формата cond в узле нет ничего, что вы не хотите копировать, и в этом случае вам нужно будет выбрать только те дочерние узлы, которые вам нужны.

Чтобы проверить, я создал следующий лист Excel (temp.xlsx), сделал только copy.paste значений и сохранил в новый файл (temp2.xlsx):

Затем запустил следующее и успешно скопировал форматирование:

public void Custom_Condition_Copy_Test()
{
    //http://stackru.com/questions/28493050/importing-excel-file-with-all-the-conditional-formatting-rules-to-epplus

    //File with custom conditional formatting
    var existingFile = new FileInfo(@"c:\temp\temp.xlsx");

    //Copy of the file with the conditonal formatting removed
    var existingFile2 = new FileInfo(@"c:\temp\temp2.xlsx");

    using (var package = new ExcelPackage(existingFile))
    using (var package2 = new ExcelPackage(existingFile2))
    {
        //Make sure there are document element for the source
        var worksheet = package.Workbook.Worksheets.First();
        var xdoc = worksheet.WorksheetXml;

        if (xdoc.DocumentElement == null)
            return;

        //Make sure there are document element for the destination
        var worksheet2 = package2.Workbook.Worksheets.First();
        var xdoc2 = worksheet2.WorksheetXml;

        if (xdoc2.DocumentElement == null)
            return;

        //get the extension list node 'extLst' from the ws with the formatting 
        var extensionlistnode = xdoc
            .DocumentElement
            .GetElementsByTagName("extLst")[0];

        //Create the import node and append it to the end of the xml document
        var newnode = xdoc2.ImportNode(extensionlistnode, true);
        xdoc2.LastChild.AppendChild(newnode);

        package2.Save();

    }
}

Возможно, вам стоит попробовать, но это должно вас сблизить.


ОБНОВЛЕНИЕ: Основано на комментарии ОП.

Если вы хотите иметь возможность добавлять пользовательский условный формат без необходимости в исходном файле, который его содержит, я вижу два варианта.

Вариант 1, вы делаете это более "правильным" способом и используете пространство имен DocumentFormat.OpenXml. НО, для этого потребуется наличие доступной библиотеки Office Open XML, которая может быть или не быть такой простой в зависимости от среды, в которой вы ее используете. Вы можете получить ее здесь http://www.microsoft.com/en-us/download/details.aspx?id=30425 и поставляется с инструментом Reflection, который может генерировать нужный код, который дает вам следующее:

using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using DocumentFormat.OpenXml;
using X14 = DocumentFormat.OpenXml.Office2010.Excel;
using Excel = DocumentFormat.OpenXml.Office.Excel;  

......

WorksheetExtensionList worksheetExtensionList1 = new WorksheetExtensionList();

WorksheetExtension worksheetExtension1 = new WorksheetExtension(){ Uri = "{78C0D931-6437-407d-A8EE-F0AAD7539E65}" };
worksheetExtension1.AddNamespaceDeclaration("x14", "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main");

X14.ConditionalFormattings conditionalFormattings1 = new X14.ConditionalFormattings();

X14.ConditionalFormatting conditionalFormatting1 = new X14.ConditionalFormatting();
conditionalFormatting1.AddNamespaceDeclaration("xm", "http://schemas.microsoft.com/office/excel/2006/main");

X14.ConditionalFormattingRule conditionalFormattingRule1 = new X14.ConditionalFormattingRule(){ Type = ConditionalFormatValues.IconSet, Priority = 2, Id = "{CD6B2710-0474-449D-881A-22CFE15D011D}" };

X14.IconSet iconSet1 = new X14.IconSet(){ IconSetTypes = X14.IconSetTypeValues.FiveArrows, Custom = true };

X14.ConditionalFormattingValueObject conditionalFormattingValueObject1 = new X14.ConditionalFormattingValueObject(){ Type = X14.ConditionalFormattingValueObjectTypeValues.Percent };
Excel.Formula formula1 = new Excel.Formula();
formula1.Text = "0";

conditionalFormattingValueObject1.Append(formula1);

X14.ConditionalFormattingValueObject conditionalFormattingValueObject2 = new X14.ConditionalFormattingValueObject(){ Type = X14.ConditionalFormattingValueObjectTypeValues.Percent };
Excel.Formula formula2 = new Excel.Formula();
formula2.Text = "20";

conditionalFormattingValueObject2.Append(formula2);

X14.ConditionalFormattingValueObject conditionalFormattingValueObject3 = new X14.ConditionalFormattingValueObject(){ Type = X14.ConditionalFormattingValueObjectTypeValues.Percent };
Excel.Formula formula3 = new Excel.Formula();
formula3.Text = "40";

conditionalFormattingValueObject3.Append(formula3);

X14.ConditionalFormattingValueObject conditionalFormattingValueObject4 = new X14.ConditionalFormattingValueObject(){ Type = X14.ConditionalFormattingValueObjectTypeValues.Percent };
Excel.Formula formula4 = new Excel.Formula();
formula4.Text = "60";

conditionalFormattingValueObject4.Append(formula4);

X14.ConditionalFormattingValueObject conditionalFormattingValueObject5 = new X14.ConditionalFormattingValueObject(){ Type = X14.ConditionalFormattingValueObjectTypeValues.Percent };
Excel.Formula formula5 = new Excel.Formula();
formula5.Text = "80";

conditionalFormattingValueObject5.Append(formula5);
X14.ConditionalFormattingIcon conditionalFormattingIcon1 = new X14.ConditionalFormattingIcon(){ IconSet = X14.IconSetTypeValues.ThreeSymbols, IconId = (UInt32Value)0U };
X14.ConditionalFormattingIcon conditionalFormattingIcon2 = new X14.ConditionalFormattingIcon(){ IconSet = X14.IconSetTypeValues.ThreeTrafficLights1, IconId = (UInt32Value)0U };
X14.ConditionalFormattingIcon conditionalFormattingIcon3 = new X14.ConditionalFormattingIcon(){ IconSet = X14.IconSetTypeValues.ThreeTriangles, IconId = (UInt32Value)0U };
X14.ConditionalFormattingIcon conditionalFormattingIcon4 = new X14.ConditionalFormattingIcon(){ IconSet = X14.IconSetTypeValues.ThreeTriangles, IconId = (UInt32Value)1U };
X14.ConditionalFormattingIcon conditionalFormattingIcon5 = new X14.ConditionalFormattingIcon(){ IconSet = X14.IconSetTypeValues.ThreeTriangles, IconId = (UInt32Value)2U };

iconSet1.Append(conditionalFormattingValueObject1);
iconSet1.Append(conditionalFormattingValueObject2);
iconSet1.Append(conditionalFormattingValueObject3);
iconSet1.Append(conditionalFormattingValueObject4);
iconSet1.Append(conditionalFormattingValueObject5);
iconSet1.Append(conditionalFormattingIcon1);
iconSet1.Append(conditionalFormattingIcon2);
iconSet1.Append(conditionalFormattingIcon3);
iconSet1.Append(conditionalFormattingIcon4);
iconSet1.Append(conditionalFormattingIcon5);

conditionalFormattingRule1.Append(iconSet1);
Excel.ReferenceSequence referenceSequence1 = new Excel.ReferenceSequence();
referenceSequence1.Text = "A1:C201";

conditionalFormatting1.Append(conditionalFormattingRule1);
conditionalFormatting1.Append(referenceSequence1);

conditionalFormattings1.Append(conditionalFormatting1);

worksheetExtension1.Append(conditionalFormattings1);

worksheetExtensionList1.Append(worksheetExtension1);
....
worksheet1.Append(worksheetExtensionList1);

Вариант 2 будет делать, как вы просите, и выполнять манипуляции со строками. Это намного проще, но это немного грязно, потому что вы путаетесь со строками, а не с объектами, но если вам нужно только установить диапазон ячеек, который выглядит не так уж плохо. Я использовал метод теста выше, чтобы извлечь строку с = extensionlistnode.OuterXml:

[TestMethod]
public void Custom_Condition_From_String_Test()
{
    //http://stackru.com/questions/28493050/importing-excel-file-with-all-the-conditional-formatting-rules-to-epplus

    //Throw in some data
    var datatable = new DataTable("tblData");
    datatable.Columns.Add(new DataColumn("Col1", typeof(int)));
    datatable.Columns.Add(new DataColumn("Col2", typeof(int)));
    datatable.Columns.Add(new DataColumn("Col3", typeof(int)));

    for (var i = 0; i < 20; i++)
    {
        var row = datatable.NewRow();
        row["Col1"] = i;
        row["Col2"] = i * 10;
        row["Col3"] = i * 100;
        datatable.Rows.Add(row);
    }

    //Copy of the file with the conditonal formatting removed
    var existingFile2 = new FileInfo(@"c:\temp\temp2.xlsx");
    if (existingFile2.Exists)
        existingFile2.Delete();

    using (var package2 = new ExcelPackage(existingFile2))
    {
        //Add the data
        var ws = package2.Workbook.Worksheets.Add("Content");
        ws.Cells.LoadFromDataTable(datatable, true);

        //The XML String extracted from the orginal excel doc using '= extensionlistnode.OuterXml'
        var cellrange = "A1:C201";
        var rawxml = String.Format(
            "<extLst xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"><ext uri=\"{{78C0D931-6437-407d-A8EE-F0AAD7539E65}}\" xmlns:x14=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/main\"><x14:conditionalFormattings><x14:conditionalFormatting xmlns:xm=\"http://schemas.microsoft.com/office/excel/2006/main\"><x14:cfRule type=\"iconSet\" priority=\"2\" id=\"{{CD6B2710-0474-449D-881A-22CFE15D011D}}\"><x14:iconSet iconSet=\"5Arrows\" custom=\"1\"><x14:cfvo type=\"percent\"><xm:f>0</xm:f></x14:cfvo><x14:cfvo type=\"percent\"><xm:f>20</xm:f></x14:cfvo><x14:cfvo type=\"percent\"><xm:f>40</xm:f></x14:cfvo><x14:cfvo type=\"percent\"><xm:f>60</xm:f></x14:cfvo><x14:cfvo type=\"percent\"><xm:f>80</xm:f></x14:cfvo><x14:cfIcon iconSet=\"3Symbols\" iconId=\"0\" /><x14:cfIcon iconSet=\"3TrafficLights1\" iconId=\"0\" /><x14:cfIcon iconSet=\"3Triangles\" iconId=\"0\" /><x14:cfIcon iconSet=\"3Triangles\" iconId=\"1\" /><x14:cfIcon iconSet=\"3Triangles\" iconId=\"2\" /></x14:iconSet></x14:cfRule><xm:sqref>{0}</xm:sqref></x14:conditionalFormatting></x14:conditionalFormattings></ext></extLst>"
            , cellrange);

        var newxdoc = new XmlDocument();
        newxdoc.LoadXml(rawxml);

        //Create the import node and append it to the end of the xml document
        var xdoc2 = ws.WorksheetXml;
        var newnode = xdoc2.ImportNode(newxdoc.FirstChild, true);
        xdoc2.LastChild.AppendChild(newnode);

        package2.Save();
    }
}
Другие вопросы по тегам