OpenXml 文档中的 CreateSpreadsheetWorkbook 示例方法直接转换为 F#。问题似乎是 Sheets 对象的 Append 方法。代码执行没有错误,但生成的 xlsx 文件缺少应该附加的内部 Xml,并且 Excel 无法读取该文件。我怀疑问题源于将功能性 F# 结构转换为 System.Collections 类型,但我没有直接证据证明这一点。
我在 C# 和 VB.NET(即文档示例)中运行了类似的代码,它完美地执行并创建了一个可读的、完整的 xlsx 文件。
我知道我可以直接处理 XML,但我想了解 F# 和 OpenXml 之间不匹配的性质。有什么建议么?
代码几乎直接来自示例:
namespace OpenXmlLib
open System
open DocumentFormat
open DocumentFormat.OpenXml
open DocumentFormat.OpenXml.Packaging
open DocumentFormat.OpenXml.Spreadsheet
module OpenXmlXL =
// this function overwrites an existing file without warning!
let CreateSpreadsheetWorkbook (filepath: string) =
// Create a spreadsheet document by supplying the filepath.
// By default, AutoSave = true, Editable = true, and Type = xlsx.
let spreadsheetDocument = SpreadsheetDocument.Create(filepath, SpreadsheetDocumentType.Workbook)
// Add a WorkbookPart to the document.
let workbookpart = spreadsheetDocument.AddWorkbookPart()
workbookpart.Workbook <- new Workbook()
// Add a WorksheetPart to the WorkbookPart.
let worksheetPart = workbookpart.AddNewPart<WorksheetPart>()
worksheetPart.Worksheet <- new Worksheet(new SheetData())
// Add Sheets to the Workbook.
let sheets = spreadsheetDocument.WorkbookPart.Workbook.AppendChild<Sheets>(new Sheets())
// Append a new worksheet and associate it with the workbook.
let sheet = new Sheet()
sheet.Id <- stringValue(spreadsheetDocument.WorkbookPart.GetIdOfPart(worksheetPart))
//Console.WriteLine(sheet.Id.Value)
sheet.SheetId <- UInt32Value(1u)
// Console.WriteLine(sheet.SheetId.Value)
sheet.Name <- StringValue("TestSheet")
//Console.WriteLine(sheet.Name.Value)
sheets.Append (sheet)
// Console.WriteLine("Sheets: {0}", sheets.InnerXml.ToString())
workbookpart.Workbook.Save()
spreadsheetDocument.Close()
工作表已创建,但为空:
工作表.xml:
<?xml version="1.0" encoding="utf-8" ?>
<x:worksheet xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main" />
workbook.xml:
<?xml version="1.0" encoding="utf-8" ?>
- <x:workbook xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
- <x:sheets>
<x:sheet name="TestSheet" sheetId="1" r:id="R263eb6f245a2497e" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" />
</x:sheets>
</x:workbook>
最佳答案
问题非常微妙,在您对 Worksheet
的调用中构造函数和 Sheets.Append
方法。这两种方法都是重载的,可以采用 seq<OpenXmlElement>
或任意数量的个人OpenXmlElement
s(通过 [<System.ParamArray>]
/params
数组)。扭曲的是 OpenXmlElement
类型本身实现 seq<OpenXmlElement>
界面。
在 C# 中,当您调用 new Worksheet(new SheetData())
,编译器的重载决议选择第二个重载,隐式创建一个包含 SheetData
的单元素数组。值(value)。但是,在 F# 中,由于 SheetData
类实现 IEnumerable<OpenXmlElement>
,选择第一个重载,这将创建一个新的 WorkSheet
通过枚举 SheetData
的内容,这不是你想要的。
要解决此问题,您需要设置调用,以便它们使用其他重载(下面的第一个示例)或显式创建单例序列(下面的第二个示例):
worksheetPart.Worksheet <- new Worksheet(new SheetData() :> OpenXmlElement)
...
sheets.Append([sheet :> OpenXmlElement])
关于f# - 无法使用带有 F# (FSharp) 的 OpenXml 附加工作表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5702939/