Ods: Add settings.xml

This commit is contained in:
2023-11-13 19:22:21 +01:00
parent 3ee7a6e75e
commit 8509f04d4d

View File

@ -1,4 +1,5 @@
using Elwig.Models.Dtos; using Elwig.Models.Dtos;
using ScottPlot;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder; using System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder;
@ -6,44 +7,36 @@ using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows;
namespace Elwig.Helpers.Export { namespace Elwig.Helpers.Export {
public class OdsFile : IDisposable, IAsyncDisposable { public class OdsFile : IDisposable {
protected readonly string FileName; protected readonly string FileName;
protected readonly ZipArchive ZipArchive; protected readonly ZipArchive ZipArchive;
protected StreamWriter? Content; protected StreamWriter? Content;
private readonly List<string> _tables;
public OdsFile(string filename) { public OdsFile(string filename) {
FileName = filename; FileName = filename;
File.Delete(filename); File.Delete(filename);
ZipArchive = ZipFile.Open(FileName, ZipArchiveMode.Create); ; ZipArchive = ZipFile.Open(FileName, ZipArchiveMode.Create);
Content = null; _tables = new List<string>();
} }
public void Dispose() { public void Dispose() {
DisposeAsync().GetAwaiter().GetResult(); AddTrailer().GetAwaiter().GetResult();
}
public async ValueTask DisposeAsync() {
await AddTrailer();
Content?.Close();
Content?.DisposeAsync();
ZipArchive?.Dispose(); ZipArchive?.Dispose();
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
private async Task AddHeader() { private async Task AddHeader() {
var mimetype = ZipArchive.CreateEntry("mimetype", CompressionLevel.NoCompression); var mimetype = ZipArchive.CreateEntry("mimetype", CompressionLevel.NoCompression);
using (var stream = mimetype.Open()) { using (var writer = new StreamWriter(mimetype.Open(), Utils.UTF8)) {
using var writer = new StreamWriter(stream, Utils.UTF8);
await writer.WriteAsync("application/vnd.oasis.opendocument.spreadsheet"); await writer.WriteAsync("application/vnd.oasis.opendocument.spreadsheet");
} }
var manifest = ZipArchive.CreateEntry("META-INF/manifest.xml"); var manifest = ZipArchive.CreateEntry("META-INF/manifest.xml");
using (var stream = manifest.Open()) { using (var writer = new StreamWriter(manifest.Open(), Utils.UTF8)) {
using var writer = new StreamWriter(stream, Utils.UTF8);
await writer.WriteAsync(""" await writer.WriteAsync("""
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.3"> <manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.3">
@ -51,14 +44,14 @@ namespace Elwig.Helpers.Export {
<manifest:file-entry manifest:full-path="content.xml" manifest:media-type="text/xml"/> <manifest:file-entry manifest:full-path="content.xml" manifest:media-type="text/xml"/>
<manifest:file-entry manifest:full-path="styles.xml" manifest:media-type="text/xml"/> <manifest:file-entry manifest:full-path="styles.xml" manifest:media-type="text/xml"/>
<manifest:file-entry manifest:full-path="meta.xml" manifest:media-type="text/xml"/> <manifest:file-entry manifest:full-path="meta.xml" manifest:media-type="text/xml"/>
<manifest:file-entry manifest:full-path="settings.xml" manifest:media-type="text/xml"/>
</manifest:manifest> </manifest:manifest>
"""); """);
} }
var styles = ZipArchive.CreateEntry("styles.xml"); var styles = ZipArchive.CreateEntry("styles.xml");
using (var stream = styles.Open()) { using (var writer = new StreamWriter(styles.Open(), Utils.UTF8)) {
using var writer = new StreamWriter(stream, Utils.UTF8);
await writer.WriteAsync(""" await writer.WriteAsync("""
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<office:document-styles xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" office:version="1.3"> <office:document-styles xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" office:version="1.3">
@ -68,8 +61,7 @@ namespace Elwig.Helpers.Export {
} }
var meta = ZipArchive.CreateEntry("meta.xml"); var meta = ZipArchive.CreateEntry("meta.xml");
using (var stream = meta.Open()) { using (var writer = new StreamWriter(meta.Open(), Utils.UTF8)) {
using var writer = new StreamWriter(stream, Utils.UTF8);
var now = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ"); var now = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");
await writer.WriteAsync($""" await writer.WriteAsync($"""
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
@ -119,7 +111,51 @@ namespace Elwig.Helpers.Export {
private async Task AddTrailer() { private async Task AddTrailer() {
if (Content == null) await AddHeader(); if (Content == null) await AddHeader();
if (Content == null) return; if (Content == null) return;
await Content.WriteAsync(" </office:spreadsheet>\r\n </office:body>\r\n</office:document-content>\r\n");
await Content.WriteAsync("""
</office:spreadsheet>
</office:body>
</office:document-content>
""");
Content.Close();
Content.Dispose();
Content = null;
var settings = ZipArchive.CreateEntry("settings.xml");
using (var writer = new StreamWriter(settings.Open(), Utils.UTF8)) {
await writer.WriteAsync("""
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<office:document-settings xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ooo="http://openoffice.org/2004/office" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" office:version="1.3">
<office:settings>
<config:config-item-set config:name="ooo:view-settings">
<config:config-item-map-indexed config:name="Views">
<config:config-item-map-entry>
<config:config-item-map-named config:name="Tables">
""");
foreach (var tbl in _tables) {
await writer.WriteAsync($"""
<config:config-item-map-entry config:name="{tbl}">
<config:config-item config:name="VerticalSplitMode" config:type="short">2</config:config-item>
<config:config-item config:name="VerticalSplitPosition" config:type="int">3</config:config-item>
<config:config-item config:name="PositionBottom" config:type="int">3</config:config-item>
</config:config-item-map-entry>
""");
}
await writer.WriteAsync("""
</config:config-item-map-named>
</config:config-item-map-entry>
</config:config-item-map-indexed>
</config:config-item-set>
</office:settings>
</office:document-settings>
""");
}
} }
public async Task AddTable<T>(DataTable<T> table) { public async Task AddTable<T>(DataTable<T> table) {
@ -127,6 +163,8 @@ namespace Elwig.Helpers.Export {
if (Content == null) return; if (Content == null) return;
var totalSpan = table.ColumnSpans.Sum(s => s.Item2); var totalSpan = table.ColumnSpans.Sum(s => s.Item2);
_tables.Add(table.FullName);
await Content.WriteAsync( await Content.WriteAsync(
$" <table:table table:name=\"{table.FullName}\">\r\n" + $" <table:table table:name=\"{table.FullName}\">\r\n" +
$" <table:table-column table:default-cell-style-name=\"default\"/>\r\n" + $" <table:table-column table:default-cell-style-name=\"default\"/>\r\n" +