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()
Run Code Online (Sandbox Code Playgroud)
工作表已创建,但为空:
sheet.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>
Run Code Online (Sandbox Code Playgroud)
kvb*_*kvb 16
问题非常微妙,并且是对Worksheet
构造函数和Sheets.Append
方法的调用.这两种方法都是重载的,可以采用一个seq<OpenXmlElement>
或任意数量的个体OpenXmlElement
(通过[<System.ParamArray>]
/ params
数组).扭曲是OpenXmlElement
类型本身实现了seq<OpenXmlElement>
接口.
在C#中,当您调用时new Worksheet(new SheetData())
,编译器的重载决策选择第二个重载,隐式创建包含该SheetData
值的单元素数组.但是,在F#中,由于SheetData
类实现了IEnumerable<OpenXmlElement>
,所以选择了第一个重载,它WorkSheet
通过枚举的内容来创建一个新的SheetData
,这不是你想要的.
要解决此问题,您需要设置调用以便它们使用其他重载(下面的第一个示例)或显式创建单个序列(下面的第二个示例):
worksheetPart.Worksheet <- new Worksheet(new SheetData() :> OpenXmlElement)
...
sheets.Append([sheet :> OpenXmlElement])
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
882 次 |
最近记录: |