将带有所有条件格式设置规则的excel文件导入到epplus

时间:2015-02-13 05:25:57

标签: c# epplus epplus-4

我有一个excel文件,其中包含大量数据以及基于单元格中的值的图标集和数据栏。它看起来像这样:enter image description here

我想导入此Excel工作表以及条件格式。有没有这个库?我经历了这个http://www.sitecorecleveland.com/resources/blogs-posts/easy_excel_interaction_pt6,但它只导入数据而不是格式化。

如果不可能,epplus中的代码会在excel表中包含这些图标集。我可以有箭头,红绿灯等,但不是这些。

1 个答案:

答案 0 :(得分:3)

我不认为EPP支持自定义条件格式,这些格式存储为" Workbook Extensions"在Excel文件的xml中。你可以复制" extLst"的xml节点。其中包含从一个工作表到另一个工作表的自定义格式。只需确保在您不希望复制的节点中的cond格式化xml旁边没有其他内容,在这种情况下,您只需要选择所需的子节点。

为了测试,我创建了以下excel表(temp.xlsx),只执行了一个copy.paste值并保存到一个新文件(temp2.​​xlsx):

enter image description here

然后运行以下内容并成功复制格式:

public void Custom_Condition_Copy_Test()
{
    //http://stackoverflow.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();

    }
}

可能想在那里试一试,但这应该让你接近。


更新:基于OP评论。

如果您希望能够添加自定义条件格式而不需要包含它的原始文件,我会看到两个选项。

选项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://stackoverflow.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();
    }
}