C# 将包含所有条件格式规则的excel文件导入epplus

C# 将包含所有条件格式规则的excel文件导入epplus,c#,epplus,epplus-4,C#,Epplus,Epplus 4,我有一个excel文件,其中包含大量数据以及基于单元格中的值的图标集和数据栏。看起来是这样的: 我想将此excel工作表与条件格式一起导入。这里有图书馆吗??我经历了这个过程,但它只导入数据,不导入格式 如果这是不可能的,epplus中是否有代码将这些IConset放在excel工作表中。我可以有箭头、交通灯等,但不能有这些。我认为EPP不支持自定义条件格式,这些格式存储为Excel文件xml中的“工作簿扩展名”。您可以将包含自定义格式的“extLst”的xml节点从一个工作表复制到另一个工作表

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

我想将此excel工作表与条件格式一起导入。这里有图书馆吗??我经历了这个过程,但它只导入数据,不导入格式


如果这是不可能的,epplus中是否有代码将这些IConset放在excel工作表中。我可以有箭头、交通灯等,但不能有这些。

我认为EPP不支持自定义条件格式,这些格式存储为Excel文件xml中的“工作簿扩展名”。您可以将包含自定义格式的“extLst”的xml节点从一个工作表复制到另一个工作表。只需确保节点中除了cond formatting xml之外没有其他不希望复制的内容,在这种情况下,您只需选择所需的子节点

为了进行测试,我创建了以下excel工作表(temp.xlsx),只对值进行了一次copy.paste,并将其保存到一个新文件(temp2.xlsx):

然后运行以下操作,并成功地将格式复制到:

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

    }
}
可能想尝试一下,但这会让你接近


更新:基于OPs评论

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

选项1,您可以使用更“正确”的方式,并使用DocumentFormat.OpenXml名称空间。但是,这将要求您拥有可用的Office Open XML库,这可能很容易,也可能不容易,这取决于您运行它的环境。您可以从这里获得它,它附带了一个反射工具,可以生成您想要的代码,从而实现以下目的:

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();
    }
}
[TestMethod]
公共无效自定义条件来自字符串测试()
{
//http://stackoverflow.com/questions/28493050/importing-excel-file-with-all-the-conditional-formatting-rules-to-epplus
//加入一些数据
var数据表=新数据表(“tblData”);
添加(新的数据列(“Col1”,typeof(int));
Add(新的DataColumn(“Col2”,typeof(int));
Add(新的DataColumn(“Col3”,typeof(int));
对于(变量i=0;i<20;i++)
{
var row=datatable.NewRow();
行[“Col1”]=i;
行[“Col2”]=i*10;
行[“Col3”]=i*100;
datatable.Rows.Add(行);
}
//已删除条件格式的文件副本
var existingFile2=新文件信息(@“c:\temp\temp2.xlsx”);
if(existingFile2.Exists)
existingFile2.Delete();
使用(var package2=new ExcelPackage(existingFile2))
{
//添加数据
var ws=package2.Workbook.Worksheets.Add(“内容”);
LoadFromDataTable(datatable,true);
//使用“=extensionlistnode.OuterXml”从原始excel文档中提取的XML字符串
var cellrange=“A1:C201”;
var rawxml=String.Format(
"020406080{0}"
,蜂窝范围);
var newxdoc=newxmldocument();
LoadXml(rawxml);
//创建导入节点并将其附加到xml文档的末尾
var xdoc2=ws.WorksheetXml;
var newnode=xdoc2.ImportNode(newxdoc.FirstChild,true);
xdoc2.LastChild.AppendChild(newnode);
package2.Save();
}
}

您提供的答案很好,是一个很好的起点。但是,在测试方法中,是否可以让包含file1格式的xml将其初始化为字符串,而不必使用file1,我们可以使用此字符串修改file2的innerxml?因为,在上面的代码中,如果在excel中对c3:f4进行格式化,那么它将对文件2执行相同的操作。也就是说,它不会在f23处格式化数据,例如?@sanmis如果我理解您的要求,您希望执行字符串操作,这样您就不需要访问第一个文件,而只需要获取原始XML?请参阅上面我的最后一次编辑。这正是我想要的。干杯