OpenXML 电子表格中的单元格样式 (SpreadsheetML)

2023-12-22

我已使用 OpenXML SDK 在 C# 中生成了一个 .xlsx 电子表格,但无法弄清楚如何使单元格样式正常工作。我一直在研究 Excel 生成的文件,但不太明白它是如何完成的。

现在,我正在创建一个填充,创建一个CellStyleFormat指向填充,创建一个CellFormat指向的索引CellStyleFormat,然后创建一个CellStyle这指向CellFormat.

这是我用来生成文档的代码:

Console.WriteLine("Creating document");
using (var spreadsheet = SpreadsheetDocument.Create("output.xlsx", SpreadsheetDocumentType.Workbook))
{
    Console.WriteLine("Creating workbook");
    spreadsheet.AddWorkbookPart();
    spreadsheet.WorkbookPart.Workbook = new Workbook();
    Console.WriteLine("Creating worksheet");
    var wsPart = spreadsheet.WorkbookPart.AddNewPart<WorksheetPart>();
    wsPart.Worksheet = new Worksheet();

    var stylesPart = spreadsheet.WorkbookPart.AddNewPart<WorkbookStylesPart>();
    stylesPart.Stylesheet = new Stylesheet();
    stylesPart.Stylesheet.Fills = new Fills();

    // create a solid red fill
    var solidRed = new PatternFill() { PatternType = PatternValues.Solid };
    solidRed.AppendChild(new BackgroundColor { Rgb = HexBinaryValue.FromString("FF00FF00") });

    stylesPart.Stylesheet.Fills.AppendChild(new Fill { PatternFill = new PatternFill() { PatternType = PatternValues.None } });
    stylesPart.Stylesheet.Fills.AppendChild(new Fill { PatternFill = solidRed });
    stylesPart.Stylesheet.CellStyleFormats = new CellStyleFormats();
    stylesPart.Stylesheet.CellStyleFormats.AppendChild(new CellFormat { FillId = 0, ApplyFill = false });
    stylesPart.Stylesheet.CellStyleFormats.AppendChild(new CellFormat { FillId = 1, ApplyFill = true });
    stylesPart.Stylesheet.CellFormats = new CellFormats();
    stylesPart.Stylesheet.CellFormats.AppendChild(new CellFormat { FormatId = 0 });
    stylesPart.Stylesheet.CellFormats.AppendChild(new CellFormat { FormatId = 1 });
    stylesPart.Stylesheet.CellStyles = new CellStyles();
    stylesPart.Stylesheet.CellStyles.AppendChild(new CellStyle { Name = "None", FormatId = 0 });
    stylesPart.Stylesheet.CellStyles.AppendChild(new CellStyle { Name = "Solid Red", FormatId = 1 });

    stylesPart.Stylesheet.Save();

    Console.WriteLine("Creating sheet data");
    var sheetData = wsPart.Worksheet.AppendChild(new SheetData());

    Console.WriteLine("Adding rows / cells...");

    var row = sheetData.AppendChild(new Row());
    row.AppendChild(new Cell() { CellValue = new CellValue("This"),  DataType = CellValues.String });
    row.AppendChild(new Cell() { CellValue = new CellValue("is"),    DataType = CellValues.String });
    row.AppendChild(new Cell() { CellValue = new CellValue("a"),     DataType = CellValues.String });
    row.AppendChild(new Cell() { CellValue = new CellValue("test."), DataType = CellValues.String });

    sheetData.AppendChild(new Row());

    row = sheetData.AppendChild(new Row());
    row.AppendChild(new Cell() { CellValue = new CellValue("Value:"),   DataType = CellValues.String });
    row.AppendChild(new Cell() { CellValue = new CellValue("123"),      DataType = CellValues.Number });
    row.AppendChild(new Cell() { CellValue = new CellValue("Formula:"), DataType = CellValues.String });
    row.AppendChild(new Cell() { CellFormula = new CellFormula("B3"),   StyleIndex = 1 }); // 

    Console.WriteLine("Saving worksheet");
    wsPart.Worksheet.Save();

    Console.WriteLine("Creating sheet list");
    var sheets = spreadsheet.WorkbookPart.Workbook.AppendChild(new Sheets());
    sheets.AppendChild(new Sheet() { Id = spreadsheet.WorkbookPart.GetIdOfPart(wsPart), SheetId = 1, Name = "Test" });

    Console.WriteLine("Saving workbook");
    spreadsheet.WorkbookPart.Workbook.Save();

    Console.WriteLine("Done.");
}

这是生成的 XML:

工作簿.xml

<?xml version="1.0" encoding="utf-8"?>
<x:workbook xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
  <x:sheets>
    <x:sheet name="Test" sheetId="1" r:id="Rbad86b8c80844a16" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" />
  </x:sheets>
</x:workbook>

样式.xml

<?xml version="1.0" encoding="utf-8"?>
<x:styleSheet xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
  <x:fills>
    <x:fill>
      <x:patternFill patternType="none" />
    </x:fill>
    <x:fill>
      <x:patternFill patternType="solid">
        <x:bgColor rgb="FF00FF00" />
      </x:patternFill>
    </x:fill>
  </x:fills>
  <x:cellStyleXfs>
    <x:xf fillId="0" applyFill="0" />
    <x:xf fillId="1" applyFill="1" />
  </x:cellStyleXfs>
  <x:cellXfs>
    <x:xf xfId="0" />
    <x:xf xfId="1" />
  </x:cellXfs>
  <x:cellStyles>
    <x:cellStyle name="None" xfId="0" />
    <x:cellStyle name="Solid Red" xfId="1" />
  </x:cellStyles>
</x:styleSheet>

工作表/sheet.xml

<?xml version="1.0" encoding="utf-8"?>
<x:worksheet xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
  <x:sheetData>
    <x:row>
      <x:c t="str"><x:v>This</x:v></x:c>
      <x:c t="str"><x:v>is</x:v></x:c>
      <x:c t="str"><x:v>a</x:v></x:c>
      <x:c t="str"><x:v>test.</x:v></x:c>
    </x:row>
    <x:row />
    <x:row>
      <x:c t="str"><x:v>Value:</x:v></x:c>
      <x:c t="n"><x:v>123</x:v></x:c>
      <x:c t="str"><x:v>Formula:</x:v></x:c>
      <x:c s="1"><x:f>B3</x:f></x:c>
    </x:row>
  </x:sheetData>
</x:worksheet>

最后一行的最后一个单元格是我尝试添加样式的位置。

当我通过 OpenXML SDK Productivity Tool 运行它时,这一切都得到了正确验证,但是,当我尝试在 Excel 中打开该文件时,出现以下错误:

修复的记录:/xl/styles.xml 部分的格式(样式)

然后会显示电子表格,但不会应用填充。

知道如何解决这个问题吗?


是的,经过大量的实验,我设法弄清楚了这一点。

事实证明,Excel分别为普通单元格和“Gray125”图案填充保留了样式0和1。上面的大部分代码都可以删除,因为我们只需要一个CellFormat really.

工作代码:

Console.WriteLine("Creating document");
using (var spreadsheet = SpreadsheetDocument.Create("output.xlsx", SpreadsheetDocumentType.Workbook))
{
    Console.WriteLine("Creating workbook");
    spreadsheet.AddWorkbookPart();
    spreadsheet.WorkbookPart.Workbook = new Workbook();
    Console.WriteLine("Creating worksheet");
    var wsPart = spreadsheet.WorkbookPart.AddNewPart<WorksheetPart>();
    wsPart.Worksheet = new Worksheet();

    var stylesPart = spreadsheet.WorkbookPart.AddNewPart<WorkbookStylesPart>();
    stylesPart.Stylesheet = new Stylesheet();

    Console.WriteLine("Creating styles");

    // blank font list
    stylesPart.Stylesheet.Fonts = new Fonts();
    stylesPart.Stylesheet.Fonts.Count = 1;
    stylesPart.Stylesheet.Fonts.AppendChild(new Font());

    // create fills
    stylesPart.Stylesheet.Fills = new Fills();

    // create a solid red fill
    var solidRed = new PatternFill() { PatternType = PatternValues.Solid };
    solidRed.ForegroundColor = new ForegroundColor { Rgb = HexBinaryValue.FromString("FFFF0000") }; // red fill
    solidRed.BackgroundColor = new BackgroundColor { Indexed = 64 };

    stylesPart.Stylesheet.Fills.AppendChild(new Fill { PatternFill = new PatternFill { PatternType = PatternValues.None } }); // required, reserved by Excel
    stylesPart.Stylesheet.Fills.AppendChild(new Fill { PatternFill = new PatternFill { PatternType = PatternValues.Gray125 } }); // required, reserved by Excel
    stylesPart.Stylesheet.Fills.AppendChild(new Fill { PatternFill = solidRed });
    stylesPart.Stylesheet.Fills.Count = 3;

    // blank border list
    stylesPart.Stylesheet.Borders = new Borders();
    stylesPart.Stylesheet.Borders.Count = 1;
    stylesPart.Stylesheet.Borders.AppendChild(new Border());

    // blank cell format list
    stylesPart.Stylesheet.CellStyleFormats = new CellStyleFormats();
    stylesPart.Stylesheet.CellStyleFormats.Count = 1;
    stylesPart.Stylesheet.CellStyleFormats.AppendChild(new CellFormat());

    // cell format list
    stylesPart.Stylesheet.CellFormats = new CellFormats();
    // empty one for index 0, seems to be required
    stylesPart.Stylesheet.CellFormats.AppendChild(new CellFormat());
    // cell format references style format 0, font 0, border 0, fill 2 and applies the fill
    stylesPart.Stylesheet.CellFormats.AppendChild(new CellFormat { FormatId = 0, FontId = 0, BorderId = 0, FillId = 2, ApplyFill = true }).AppendChild(new Alignment { Horizontal = HorizontalAlignmentValues.Center });
    stylesPart.Stylesheet.CellFormats.Count = 2;

    stylesPart.Stylesheet.Save();

    Console.WriteLine("Creating sheet data");
    var sheetData = wsPart.Worksheet.AppendChild(new SheetData());

    Console.WriteLine("Adding rows / cells...");

    var row = sheetData.AppendChild(new Row());
    row.AppendChild(new Cell() { CellValue = new CellValue("This"),  DataType = CellValues.String });
    row.AppendChild(new Cell() { CellValue = new CellValue("is"),    DataType = CellValues.String });
    row.AppendChild(new Cell() { CellValue = new CellValue("a"),     DataType = CellValues.String });
    row.AppendChild(new Cell() { CellValue = new CellValue("test."), DataType = CellValues.String });

    sheetData.AppendChild(new Row());

    row = sheetData.AppendChild(new Row());
    row.AppendChild(new Cell() { CellValue = new CellValue("Value:"),   DataType = CellValues.String });
    row.AppendChild(new Cell() { CellValue = new CellValue("123"),      DataType = CellValues.Number });
    row.AppendChild(new Cell() { CellValue = new CellValue("Formula:"), DataType = CellValues.String });
    // style index = 1, i.e. point at our fill format
    row.AppendChild(new Cell() { CellFormula = new CellFormula("B3"),   DataType = CellValues.Number, StyleIndex = 1 });

    Console.WriteLine("Saving worksheet");
    wsPart.Worksheet.Save();

    Console.WriteLine("Creating sheet list");
    var sheets = spreadsheet.WorkbookPart.Workbook.AppendChild(new Sheets());
    sheets.AppendChild(new Sheet() { Id = spreadsheet.WorkbookPart.GetIdOfPart(wsPart), SheetId = 1, Name = "Test" });

    Console.WriteLine("Saving workbook");
    spreadsheet.WorkbookPart.Workbook.Save();

    Console.WriteLine("Done.");
}

一些忠告:

如果您想避免这种疯狂的情况,请使用 ClosedXML。

我不能推荐封闭XML https://github.com/closedxml/closedxml如果你正在做这种工作,那就足够了。OpenXML API 和格式本身使用起来非常乏味,并且存在各种未记录的情况。 ClosedXML 为您完成了很多琐碎的工作。他们也非常擅长快速修复错误。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenXML 电子表格中的单元格样式 (SpreadsheetML) 的相关文章

  • 将处理后的图形绘制到另一个图形中

    我想将一个经过处理的图形绘制到另一个图形中 I have two graphics var gHead Graphics FromImage h var gBackground Graphics FromImage b Transform
  • 在 OpenCL 中将函数作为参数传递

    是否可以在 OpenCL 1 2 中将函数指针传递给内核 我知道可以用C实现 但不知道如何在OpenCL的C中实现 编辑 我想做这篇文章中描述的同样的事情 在 C 中如何将函数作为参数传递 https stackoverflow com q
  • 捕获 foreach 条件中抛出的异常

    我有一个foreach在 foreach 本身的条件下循环期间中断的循环 有没有办法try catch抛出异常然后继续循环的项 这将运行几次 直到异常发生然后结束 try foreach b in bees exception is in
  • 在 VBA Excel 中查找、剪切和插入行以匹配借项和贷项值

    我在 Sheet1 中有以下设置数据 并从第 4 行 A 列开始 其中标题位于第 3 行 No Date Code Name Remarks D e b i t Cr e d i t 1 4 30 2015 004 AB 01 04 15
  • 在 Xcode4 中使用 Boost

    有人设置 C Xcode4 项目来使用 Boost 吗 对于一个简单的 C 控制台应用程序 我需要在 Xcode 中设置哪些设置 Thanks 用这个来管理它 和这个
  • 获取从属性构造函数内部应用到哪个属性的成员?

    我有一个自定义属性 在自定义属性的构造函数内 我想将属性的属性值设置为属性所应用到的属性的类型 是否有某种方式可以访问该属性所应用到的成员从我的属性类内部 可以从 NET 4 5 using CallerMemberName Somethi
  • 如何在 VS 中键入时显示方法的完整文档?

    标题非常具有描述性 是否有任何扩展可以让我看到我正在输入的方法的完整文档 我想查看文档 因为我可以在对象浏览器中看到它 其中包含参数的描述和所有内容 而不仅仅是一些 摘要 当然可以选择查看所有覆盖 它可能是智能感知的一部分 或者我不知道它并
  • VS30063:您无权访问 https://dev.azure.com

    我正在尝试在 asp net core 2 1 mvc 应用程序中使用以下代码连接 Azure DevOps Uri orgUrl new Uri https dev azure com xxxxx String personalAcces
  • 为什么密码错误会导致“填充无效且无法删除”?

    我需要一些简单的字符串加密 所以我编写了以下代码 有很多 灵感 来自here http www codeproject com KB security DotNetCrypto aspx create and initialize a cr
  • 为什么 std::allocator 在 C++17 中丢失成员类型/函数?

    一边看着std 分配器 http en cppreference com w cpp memory allocator 我看到成员 value type pointer const pointer reference const refer
  • 事件日志写入错误

    很简单 我想向事件日志写入一些内容 protected override void OnStop TODO Add code here to perform any tear down necessary to stop your serv
  • C# 编译器如何决定发出可重定向的程序集引用?

    NET Compact Framework 引入了可重定向程序集引用 现在用于支持可移植类库 基本上 编译器会发出以下 MSIL assembly extern retargetable mscorlib publickeytoken 7C
  • 通过等待任务或访问其 Exception 属性都没有观察到任务的异常

    这些是我的任务 我应该如何修改它们以防止出现此错误 我检查了其他类似的线程 但我正在使用等待并继续 那么这个错误是怎么发生的呢 通过等待任务或访问其 Exception 属性都没有观察到任务的异常 结果 未观察到的异常被终结器线程重新抛出
  • 32位PPC rlwinm指令

    我在理解上有点困难rlwinmPPC 汇编指令 旋转左字立即然后与掩码 我正在尝试反转函数的这一部分 rlwinm r3 r3 0 28 28 我已经知道什么了r3 is r3在本例中是一个 4 字节整数 但我不确定这条指令到底是什么rlw
  • gdb查找行号的内存地址

    假设我已将 gdb 附加到一个进程 并且在其内存布局中有一个文件和行号 我想要其内存地址 如何获取文件x中第n行的内存地址 这是在 Linux x86 上 gdb info line test c 56 Line 56 of test c
  • 内核开发和 C++ [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 从我know https stackoverflow com questions 580292 what languages are windo
  • 运行代码首先迁移更新数据库时出错

    我在迁移到数据库时遇到问题 并且似乎找不到我遇到的错误的答案 System MissingMethodException Method not found System Data Entity Migrations Builders Tab
  • 过度使用委托对性能来说是一个坏主意吗? [复制]

    这个问题在这里已经有答案了 考虑以下代码 if IsDebuggingEnabled instance Log GetDetailedDebugInfo GetDetailedDebugInfo 可能是一个昂贵的方法 因此我们只想在调试模式
  • Azure函数版本2.0-应用程序blobTrigger不工作

    我有一个工作功能应用程序 它有一个 blob 输入和一个事件中心输出 在测试版中工作 随着最新的更改 我的功能不再起作用 我尝试根据发行说明更新 host json 文件 但它没有引用 blob 触发器 version 2 0 extens
  • 从类模板参数为 asm 生成唯一的字符串文字

    我有一个非常特殊的情况 我需要为类模板中声明的变量生成唯一的汇编程序名称 我需要该名称对于类模板的每个实例都是唯一的 并且我需要将其传递给asm关键字 see here https gcc gnu org onlinedocs gcc 12

随机推荐

  • getSupportFragmentManager getFragment 不带标签或 id

    我正在开发 Android 3 1 平板电脑应用程序 我在一项活动中使用 ViewPager 和片段 我的问题是我不知道如何为片段设置 ID 或标签 Activity public class FillEReportFragmentActi
  • 如何设置跨域标头以允许数据 URL?

    我有一个 javascript 脚本 它接受 SVG 字符串并尝试将其放在画布上 以对其进行光栅化 这在 Chrome 和 Firefox 中运行良好 但 Safari 会抛出错误 var img new Image img onload
  • CefSharp WPF 错误

    已使用 CefSharp 在 WPF 项目中使用 chromium Web 浏览器 构建按预期工作 但发布时收到的错误是 对与特定绑定约束匹配的类型 CefSharp Wpf ChromiumWebBrowser 的构造函数的调用引发了异常
  • 如何在git中合并提交之前找到两个分支的共同祖先?

    背景 我正在尝试编写一个脚本来简化使用 git 的向后移植过程 修复当前版本中的错误的一般过程如下 分支来自master到错误修复分支 例如bugfix abc 进行所有提交以修复错误bugfix abc Merge bugfix abc
  • 将生成的 GIF 保存到相机胶卷吗?

    谢谢阅读 我使用这个问题的方法创建了一个 GIF 通过 iOS 创建并导出 gif 动画 https stackoverflow com questions 14915138 create and and export an animate
  • 指定的架构无效。错误:“System.Data.Spatial.DbGeography”无法映射到原始类型

    我首先正在做实体框架 v6 数据库 尝试从我的数据上下文访问数据时出现以下错误 未加载关系 Model FK Table1 Table2 因为类型 Model Table1 不可用 以下信息可能有助于解决之前的错误 类型 Model Tab
  • Windows 上的 nohup 是什么?

    我想运行这样的 Java jar 文件 java jar spider jar 如何在Windows上后台运行它 在 Linux 上就像这样 nohup java jar spider jar gt var tmp spider log 2
  • popBackStack 后 ViewPager 中的片段未恢复

    Problem 从另一个片段返回后 片段不会重新附加到其托管 ViewPager 情况 一个 Activity 托管一个 Fragment 其布局包含一个 ViewPager PageListFragment在下面的例子中 ViewPage
  • Android Studio vs Eclipse + ADT 插件? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 对于这个问题我想得到客观的回答 为什么我应该使用 Android Studio 遇到问题和复杂的任务 例如导入为 Eclipse 开发的库 对我
  • 您在程序中使用“kibibyte”作为度量单位吗? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何将输出参数传递给存储过程?

    我编写了一个存储过程 格式如下 ALTER PROCEDURE usp data migration sourceDatabase varchar 50 sourceTable varchar 50 targetDatabase varch
  • 登录后 MVC 重定向

    我有一个 AccountController 用户可以在其中登录 还有一个名为 Admin 的区域 用户必须被授权才能查看 当用户使用正确的用户名和密码登录时 它会再次重定向到同一页面 Account Login ReturnUrl 2FA
  • 使用 Maven-3 使用 archiva 重新部署时出现 Http 409 错误

    我正在将 jar 文件部署到 Maven 存储库 archiva pom xml
  • 如何在Ocaml中快速将树结构打印成字符串?

    假设我在 OCaml 中有一个 树 形式的数学表达式 它被表示为如下的代数类型 type expr Number of int Plus of expr expr 嗯 这是一个very简化的定义 但足以描述问题 我想将其转换为逆波兰表示法的
  • 使用 Django Forms 来显示和编辑?

    我正在研究如何在 Django 中最好地创建可用于显示或编辑数据的 HTML 页面 也就是说 我希望字段的值在显示模式下显示为文本 但在编辑 添加模式下显示在其小部件中 看来 Django 的设计初衷并不是这样做 这些字段总是出现在它们的小
  • 如何在 iPhone 中以编程方式获取应用程序的存储大小

    I want to get the Storage Sizes of each Applications in iPhone through objective C Any one help to get like this 假设您正在为越
  • C++.Net 程序集可以轻松反编译吗?

    我知道所有程序集都可以以某种方式反编译 但 C 和 VB 应用程序最容易使用 Net Reflector 等工具反编译为源代码 所以我的问题是 如果我使用 C 的 Net 程序集和函数来编写应用程序 是否可以轻松反编译它 就好像它是带有 N
  • 将应用程序从 Carbon 迁移到 Cocoa

    我正在开发一个应用程序 需要将其整个代码从carbon迁移到cocoa 我在大学期间和实习期间有C C python和Java编程经验 但从未接触过Objective C或做过在此之前的任何 Mac Carbon 和 Cocoa 编程 那么
  • 适用于 iOS 的 GA 和自定义尺寸

    我们在 iOS 应用程序中设置了 Google Analytics 该应用程序发送供应商标识符以区分报告中的用户 这是我们所做的 在 Google Analytics 中 我们设置了一个自定义维度 如下所示 名称 用户标识符 范围 用户 主
  • OpenXML 电子表格中的单元格样式 (SpreadsheetML)

    我已使用 OpenXML SDK 在 C 中生成了一个 xlsx 电子表格 但无法弄清楚如何使单元格样式正常工作 我一直在研究 Excel 生成的文件 但不太明白它是如何完成的 现在 我正在创建一个填充 创建一个CellStyleForma