【问题标题】:C# OpenXML-only specific cell styling for Excel export用于 Excel 导出的 C# OpenXML-only 特定单元格样式
【发布时间】:2016-01-19 23:45:54
【问题描述】:

我对 C# 比较陌生。以下是我目前拥有的代码。它适用于将 DataTable 转换为 Excel 格式的可导出字节数组。我首先在填充的 DataSet 上调用 Create(),将其存储在 Byte[] 中,然后由 DataSet 中的数据填充。请注意,下面的所有代码都可以完美运行,我希望根据特定条件为导出的 excel 文件添加一些样式。我想知道这样的“if”(?)语句可以去哪里,因为我可以在哪里添加这个样式信息,给定我的特定约束(我应该识别特定行中的数据并突出显示它们。)我已经考虑到我正在使用的实现,在线尝试了很多资源,几乎每个资源都存在问题。我也不允许使用标准 OpenXML 之外的任何库。

    public static Byte[] Create(DataSet ds)
    {
        Dictionary<String, List<OpenXmlElement>> sets = ToSheets(ds);
        Byte[] _data = new Byte[] { };

        using (MemoryStream _ms = new MemoryStream())
        {
            using (SpreadsheetDocument package = SpreadsheetDocument.Create(_ms, SpreadsheetDocumentType.Workbook))
            {
                WorkbookPart workbookpart = package.AddWorkbookPart();
                workbookpart.Workbook = new Workbook();

                Sheets sheets = workbookpart.Workbook.AppendChild(new Sheets());
                foreach (KeyValuePair<String, List<OpenXmlElement>> set in sets)
                {
                    WorksheetPart worksheetpart = workbookpart.AddNewPart<WorksheetPart>();
                    worksheetpart.Worksheet = new Worksheet(new SheetData(set.Value));
                    worksheetpart.Worksheet.Save();

                    Sheet sheet = new Sheet()
                    {
                        Id = workbookpart.GetIdOfPart(worksheetpart),
                        SheetId = Convert.ToUInt32(sheets.Count() + 1),
                        Name = set.Key
                    };
                    sheets.AppendChild(sheet);
                }
                workbookpart.Workbook.Save();
            }
            _data = _ms.ToArray();
        }
        return _data;
    }

上面是主要的 Create() 函数,下面是 ToSheets() 函数。它应该是不言自明的。

    public static Dictionary<String, List<OpenXmlElement>> ToSheets(DataSet ds)
    {
        return
            (from dt in ds.Tables.OfType<DataTable>()
             select new
             {
                 Key = dt.TableName,
                 Value = (
                 new List<OpenXmlElement>(
                    new OpenXmlElement[] 
            {
                new Row(
                    from d in dt.Columns.OfType<DataColumn>()
                    select (OpenXmlElement)new Cell()
                    {
                        CellValue = new CellValue(d.ColumnName),
                        DataType = CellValues.String
                    })
            })).Union
                 ((from dr in dt.Rows.OfType<DataRow>()
                   select ((OpenXmlElement)new Row(from dc in dr.ItemArray
                                                   select (OpenXmlElement)new Cell()
                                                   {
                                                       CellValue = new CellValue(dc.ToString()),
                                                       DataType = CellValues.String
                                                   })))).ToList()
             }).ToDictionary(p => p.Key, p => p.Value);
    }

如果有人能指出我可以在哪里附加样式信息以及如何执行此操作的正确方向,我将不胜感激(请记住,我必须根据行中的数据设置行的样式,即行具有某些单元格值的行应该以特定方式设置样式。)具体来说,当所述行中的第一个单元格包含数据(例如“X”)时,我正在寻找具有蓝色背景且没有边框的行中的单元格样式。

感谢您的宝贵时间!

【问题讨论】:

    标签: c# excel openxml openxml-sdk


    【解决方案1】:

    我自己设法解决了这个问题。我在this page 添加了样式信息。

    然后我修改了自己的代码以反映选择性更改。

        public Dictionary<String, List<OpenXmlElement>> ToSheets(DataSet ds)
        {
            return
                (from dt in ds.Tables.OfType<DataTable>()
                 select new
                 {
                     Key = dt.TableName,
                     Value = (
                     new List<OpenXmlElement>(
                        new OpenXmlElement[] 
                {
                    new Row(
                        from d in dt.Columns.OfType<DataColumn>()
                        select (OpenXmlElement)new Cell()
                        {
                            CellValue = new CellValue(d.ColumnName),
                            StyleIndex = 1,
                            DataType = CellValues.String
                        })
                })).Union
                     ((from dr in dt.Rows.OfType<DataRow>()
                       select ((OpenXmlElement)new Row(from dc in dr.ItemArray
                                                       select (OpenXmlElement)new Cell()
                                                       {
                                                           CellValue = new CellValue(dc.ToString()),
                                                           DataType = CellValues.String,
                                                           StyleIndex = styleIdentifier(dc.ToString())
                                                       })))).ToList()
                 }).ToDictionary(p => p.Key, p => p.Value);
        }
    

    很明显,我使用上面的链接指南通过将多个子元素附加到 stylesPart.Stylesheet.CellFormats 来定义多个 StyleIndex 值。有效!然后我简单地使用下面的函数来动态识别我想要为每个特定行附加的样式信息。

        public UInt32Value styleIdentifier(String str)
        {
            int temp;
    
            xCount.Value = (Convert.ToInt32(this.xCount.Value) + 1).ToString();
    
            if (int.TryParse(str, out temp))
            { xCount.Value = "0"; }
    
            if (Convert.ToInt32(this.xCount.Value) < 4)
            { return 2; }
    
            return 3;
        }
    

    在代码前端,我只是将“xCount”用作初始值 >5 的 HiddenField 值。 这样,对于从第 1 列中的数据标识为要突出显示的行的每一行,每个单元格都会突出显示(最多 4 个,假设我有 4 列)。然后重置 xCount 的值,直到遇到另一个这样的单元格并重复该过程,直到遇到下一个要突出显示的行。

    再次感谢 StackOverflow 聊天室的好人,特别是 @juanvan 为我指引正确的方向!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多