Importing excel file with all the conditional formatting rules to epplus

 ̄綄美尐妖づ 提交于 2019-12-18 09:03:56

问题


I have an excel file which contains lots of data along with icon sets and data bars based on the values in the cell. It looks like this:

I want to import this excel sheet along with the conditional formatting. Is there any library for this?? I went through this http://www.sitecorecleveland.com/resources/blogs-posts/easy_excel_interaction_pt6 but it only imports data not format.

If that's not possible is there code in epplus to have these iconsets in excel sheet. I can have arrows, traffic lights, etc but not these.


回答1:


I dont think EPP supports custom conditional formatting which are stored as "Workbook Extensions" in the xml of the Excel file. You could copy the xml node of the "extLst" which contains the custom formatting from one worksheet to another. Just make sure there is nothing else beside the cond formatting xml in the node that you do not want copied in which case you will have to select only the child nodes you want.

To test, i created the following excel sheet (temp.xlsx), did a copy.paste of values only and saved to a new file (temp2.xlsx):

Then ran the following and it successfully copied the formatting over:

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

    }
}

Might want to put some try's in there but this should get you close.


UPDATE: Based on OPs comment.

If you want to be able to add the custom conditional format without the need of the original file that contains it, I see two options.

Option 1, you do it the more "correct" way and use the DocumentFormat.OpenXml namespace. BUT, this would require you to have the Office Open XML library available which may or may not be so easy depending on the environment you are running this in. You can get it from here http://www.microsoft.com/en-us/download/details.aspx?id=30425 and it comes with a Reflection tool that can generate the code you want which gets you this:

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

Option 2 would be to do as you are asking and perform string manipulation. This is much easier but it is a slightly dirty in that you are messing with strings rather then objects but if the only thing you need to set is the cell range that doesnt seem so bad. I used the test method above to extract the string with = 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();
    }
}


来源:https://stackoverflow.com/questions/28493050/importing-excel-file-with-all-the-conditional-formatting-rules-to-epplus

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!