xlsxrb 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.devcontainer/Dockerfile +64 -0
- data/.devcontainer/devcontainer.json +17 -0
- data/CHANGELOG.md +12 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +384 -0
- data/Rakefile +290 -0
- data/benchmark.rb +390 -0
- data/docs/ARCHITECTURE.md +488 -0
- data/docs/SPEC_SOURCES.md +42 -0
- data/docs/visual/VisualGallery.md +4684 -0
- data/docs/wasm/wasm_doc_helper.css +189 -0
- data/docs/wasm/wasm_doc_helper.js +320 -0
- data/lib/xlsxrb/elements/cell.rb +77 -0
- data/lib/xlsxrb/elements/column.rb +28 -0
- data/lib/xlsxrb/elements/row.rb +47 -0
- data/lib/xlsxrb/elements/types.rb +36 -0
- data/lib/xlsxrb/elements/workbook.rb +47 -0
- data/lib/xlsxrb/elements/worksheet.rb +50 -0
- data/lib/xlsxrb/elements.rb +15 -0
- data/lib/xlsxrb/ooxml/reader.rb +8048 -0
- data/lib/xlsxrb/ooxml/shared_strings_parser.rb +75 -0
- data/lib/xlsxrb/ooxml/styles_parser.rb +194 -0
- data/lib/xlsxrb/ooxml/utils.rb +122 -0
- data/lib/xlsxrb/ooxml/workbook_parser.rb +78 -0
- data/lib/xlsxrb/ooxml/workbook_writer.rb +1000 -0
- data/lib/xlsxrb/ooxml/worksheet_parser.rb +455 -0
- data/lib/xlsxrb/ooxml/worksheet_writer.rb +1008 -0
- data/lib/xlsxrb/ooxml/writer.rb +5450 -0
- data/lib/xlsxrb/ooxml/xml_builder.rb +113 -0
- data/lib/xlsxrb/ooxml/xml_parser.rb +68 -0
- data/lib/xlsxrb/ooxml/zip_generator.rb +162 -0
- data/lib/xlsxrb/ooxml/zip_reader.rb +158 -0
- data/lib/xlsxrb/ooxml/zip_writer.rb +213 -0
- data/lib/xlsxrb/ooxml.rb +22 -0
- data/lib/xlsxrb/style_builder.rb +241 -0
- data/lib/xlsxrb/version.rb +5 -0
- data/lib/xlsxrb.rb +1427 -0
- data/measure_memory.rb +42 -0
- data/sig/xlsxrb.rbs +23 -0
- data/vendor/sdk_runner/Program.cs +91 -0
- data/vendor/sdk_runner/sdk_runner.csproj +13 -0
- metadata +144 -0
data/measure_memory.rb
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "opentelemetry/sdk"
|
|
4
|
+
require "objspace"
|
|
5
|
+
require_relative "lib/xlsxrb"
|
|
6
|
+
|
|
7
|
+
# Outputs memory and GC stats for a given tracing span
|
|
8
|
+
class MemorySpanProcessor < OpenTelemetry::SDK::Trace::SpanProcessor
|
|
9
|
+
def on_start(span, _parent_context)
|
|
10
|
+
span.set_attribute("ruby.gc.count.start", GC.stat[:count])
|
|
11
|
+
span.set_attribute("ruby.memory.bytes_allocated.start", ObjectSpace.memsize_of_all)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def on_finish(span)
|
|
15
|
+
gc_start = span.attributes["ruby.gc.count.start"]
|
|
16
|
+
mem_start = span.attributes["ruby.memory.bytes_allocated.start"]
|
|
17
|
+
|
|
18
|
+
gc_diff = GC.stat[:count] - (gc_start || 0)
|
|
19
|
+
mem_diff = ObjectSpace.memsize_of_all - (mem_start || 0)
|
|
20
|
+
|
|
21
|
+
mem_mb = mem_diff.to_f / 1024 / 1024
|
|
22
|
+
|
|
23
|
+
puts "[#{span.name}] Memory delta: #{mem_mb.round(2)} MB, GC count: #{gc_diff}"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
OpenTelemetry::SDK.configure do |c|
|
|
28
|
+
c.add_span_processor(MemorySpanProcessor.new)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
puts "Generating 100,000 cells (10,000 rows x 10 cols) to measure memory..."
|
|
32
|
+
|
|
33
|
+
# Using a smaller size first so it runs quickly
|
|
34
|
+
Xlsxrb.generate("test_memory.xlsx") do |w|
|
|
35
|
+
w.add_sheet("Data") do
|
|
36
|
+
10_000.times do |i|
|
|
37
|
+
w.add_row(["A", "B", "C", "D", "E", "F", "G", "H", "I", i])
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
puts "Done."
|
data/sig/xlsxrb.rbs
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Xlsxrb
|
|
2
|
+
VERSION: String
|
|
3
|
+
|
|
4
|
+
module Ooxml
|
|
5
|
+
class Event
|
|
6
|
+
attr_reader type: Symbol
|
|
7
|
+
attr_reader args: Array[untyped]
|
|
8
|
+
attr_reader source: Hash[Symbol, untyped]
|
|
9
|
+
|
|
10
|
+
def self.new: (type: Symbol, args: Array[untyped], source: Hash[Symbol, untyped]) -> Event
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class WorksheetParser
|
|
14
|
+
def self.each_event: (String, ?shared_strings: Array[String], ?part_name: String) ?{ (Event) -> void } -> void
|
|
15
|
+
| (String, ?shared_strings: Array[String], ?part_name: String) -> Enumerator[Event, void]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class SharedStringsParser
|
|
19
|
+
def self.each_event: (String, ?part_name: String) ?{ (Event) -> void } -> void
|
|
20
|
+
| (String, ?part_name: String) -> Enumerator[Event, void]
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
using Microsoft.CodeAnalysis.CSharp.Scripting;
|
|
2
|
+
using Microsoft.CodeAnalysis.Scripting;
|
|
3
|
+
using DocumentFormat.OpenXml.Packaging;
|
|
4
|
+
using DocumentFormat.OpenXml.Validation;
|
|
5
|
+
|
|
6
|
+
if (args.Length < 2)
|
|
7
|
+
{
|
|
8
|
+
Console.Error.WriteLine("Usage: dotnet run --project vendor/sdk_runner -- <scenario.cs> <xlsx-path>");
|
|
9
|
+
return 2;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
var scenarioPath = Path.GetFullPath(args[0]);
|
|
13
|
+
var xlsxPath = Path.GetFullPath(args[1]);
|
|
14
|
+
|
|
15
|
+
if (!File.Exists(scenarioPath))
|
|
16
|
+
{
|
|
17
|
+
Console.Error.WriteLine($"Scenario file not found: {scenarioPath}");
|
|
18
|
+
return 2;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (!File.Exists(xlsxPath))
|
|
22
|
+
{
|
|
23
|
+
Console.Error.WriteLine($"XLSX file not found: {xlsxPath}");
|
|
24
|
+
return 2;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
var code = await File.ReadAllTextAsync(scenarioPath);
|
|
28
|
+
var result = await RunScenario(code, xlsxPath);
|
|
29
|
+
if (result.Success)
|
|
30
|
+
{
|
|
31
|
+
Console.WriteLine("SCENARIO_PASS");
|
|
32
|
+
return 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
Console.Error.WriteLine(result.ErrorOutput);
|
|
36
|
+
return 1;
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
async Task<ScenarioExecResult> RunScenario(string code, string xlsxPath)
|
|
40
|
+
{
|
|
41
|
+
var globals = new ScenarioContext(xlsxPath);
|
|
42
|
+
|
|
43
|
+
var options = ScriptOptions.Default
|
|
44
|
+
.AddReferences(
|
|
45
|
+
typeof(object).Assembly,
|
|
46
|
+
typeof(Enumerable).Assembly,
|
|
47
|
+
typeof(Console).Assembly,
|
|
48
|
+
typeof(SpreadsheetDocument).Assembly,
|
|
49
|
+
typeof(OpenXmlValidator).Assembly
|
|
50
|
+
)
|
|
51
|
+
.AddImports(
|
|
52
|
+
"System",
|
|
53
|
+
"System.IO",
|
|
54
|
+
"System.Linq",
|
|
55
|
+
"System.Collections.Generic",
|
|
56
|
+
"DocumentFormat.OpenXml",
|
|
57
|
+
"DocumentFormat.OpenXml.Packaging",
|
|
58
|
+
"DocumentFormat.OpenXml.Spreadsheet",
|
|
59
|
+
"DocumentFormat.OpenXml.Validation",
|
|
60
|
+
"DocumentFormat.OpenXml.CustomProperties",
|
|
61
|
+
"DocumentFormat.OpenXml.VariantTypes"
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
try
|
|
65
|
+
{
|
|
66
|
+
await CSharpScript.RunAsync(code, options, globals, typeof(ScenarioContext));
|
|
67
|
+
return new ScenarioExecResult { Success = true };
|
|
68
|
+
}
|
|
69
|
+
catch (CompilationErrorException ex)
|
|
70
|
+
{
|
|
71
|
+
var errorMsg = "SCENARIO_COMPILE_ERROR\n" + string.Join("\n", ex.Diagnostics.Select(d => d.ToString()));
|
|
72
|
+
return new ScenarioExecResult { Success = false, ErrorOutput = errorMsg };
|
|
73
|
+
}
|
|
74
|
+
catch (Exception ex)
|
|
75
|
+
{
|
|
76
|
+
var errorMsg = "SCENARIO_FAIL\n" + ex.ToString();
|
|
77
|
+
return new ScenarioExecResult { Success = false, ErrorOutput = errorMsg };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
record ScenarioExecResult(bool Success = false, string ErrorOutput = "");
|
|
82
|
+
|
|
83
|
+
public sealed class ScenarioContext
|
|
84
|
+
{
|
|
85
|
+
public ScenarioContext(string xlsxPath)
|
|
86
|
+
{
|
|
87
|
+
XlsxPath = xlsxPath;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public string XlsxPath { get; }
|
|
91
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
|
2
|
+
<PropertyGroup>
|
|
3
|
+
<OutputType>Exe</OutputType>
|
|
4
|
+
<TargetFramework>net8.0</TargetFramework>
|
|
5
|
+
<ImplicitUsings>enable</ImplicitUsings>
|
|
6
|
+
<Nullable>enable</Nullable>
|
|
7
|
+
</PropertyGroup>
|
|
8
|
+
|
|
9
|
+
<ItemGroup>
|
|
10
|
+
<PackageReference Include="DocumentFormat.OpenXml" Version="3.0.2" />
|
|
11
|
+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.11.0" />
|
|
12
|
+
</ItemGroup>
|
|
13
|
+
</Project>
|
metadata
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: xlsxrb
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- niku
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: opentelemetry-api
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '1.4'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '1.4'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: rexml
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: ruby_wasm
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0'
|
|
47
|
+
type: :development
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: webrick
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0'
|
|
68
|
+
description: A minimal dependency XLSX reading and writing library for Ruby, relying
|
|
69
|
+
on standard libraries for core logic and opentelemetry-api for observability.
|
|
70
|
+
email:
|
|
71
|
+
- 10890+niku@users.noreply.github.com
|
|
72
|
+
executables: []
|
|
73
|
+
extensions: []
|
|
74
|
+
extra_rdoc_files: []
|
|
75
|
+
files:
|
|
76
|
+
- ".devcontainer/Dockerfile"
|
|
77
|
+
- ".devcontainer/devcontainer.json"
|
|
78
|
+
- CHANGELOG.md
|
|
79
|
+
- CODE_OF_CONDUCT.md
|
|
80
|
+
- LICENSE.txt
|
|
81
|
+
- README.md
|
|
82
|
+
- Rakefile
|
|
83
|
+
- benchmark.rb
|
|
84
|
+
- docs/ARCHITECTURE.md
|
|
85
|
+
- docs/SPEC_SOURCES.md
|
|
86
|
+
- docs/visual/VisualGallery.md
|
|
87
|
+
- docs/wasm/wasm_doc_helper.css
|
|
88
|
+
- docs/wasm/wasm_doc_helper.js
|
|
89
|
+
- lib/xlsxrb.rb
|
|
90
|
+
- lib/xlsxrb/elements.rb
|
|
91
|
+
- lib/xlsxrb/elements/cell.rb
|
|
92
|
+
- lib/xlsxrb/elements/column.rb
|
|
93
|
+
- lib/xlsxrb/elements/row.rb
|
|
94
|
+
- lib/xlsxrb/elements/types.rb
|
|
95
|
+
- lib/xlsxrb/elements/workbook.rb
|
|
96
|
+
- lib/xlsxrb/elements/worksheet.rb
|
|
97
|
+
- lib/xlsxrb/ooxml.rb
|
|
98
|
+
- lib/xlsxrb/ooxml/reader.rb
|
|
99
|
+
- lib/xlsxrb/ooxml/shared_strings_parser.rb
|
|
100
|
+
- lib/xlsxrb/ooxml/styles_parser.rb
|
|
101
|
+
- lib/xlsxrb/ooxml/utils.rb
|
|
102
|
+
- lib/xlsxrb/ooxml/workbook_parser.rb
|
|
103
|
+
- lib/xlsxrb/ooxml/workbook_writer.rb
|
|
104
|
+
- lib/xlsxrb/ooxml/worksheet_parser.rb
|
|
105
|
+
- lib/xlsxrb/ooxml/worksheet_writer.rb
|
|
106
|
+
- lib/xlsxrb/ooxml/writer.rb
|
|
107
|
+
- lib/xlsxrb/ooxml/xml_builder.rb
|
|
108
|
+
- lib/xlsxrb/ooxml/xml_parser.rb
|
|
109
|
+
- lib/xlsxrb/ooxml/zip_generator.rb
|
|
110
|
+
- lib/xlsxrb/ooxml/zip_reader.rb
|
|
111
|
+
- lib/xlsxrb/ooxml/zip_writer.rb
|
|
112
|
+
- lib/xlsxrb/style_builder.rb
|
|
113
|
+
- lib/xlsxrb/version.rb
|
|
114
|
+
- measure_memory.rb
|
|
115
|
+
- sig/xlsxrb.rbs
|
|
116
|
+
- vendor/sdk_runner/Program.cs
|
|
117
|
+
- vendor/sdk_runner/sdk_runner.csproj
|
|
118
|
+
homepage: https://github.com/niku/xlsxrb
|
|
119
|
+
licenses:
|
|
120
|
+
- MIT
|
|
121
|
+
metadata:
|
|
122
|
+
allowed_push_host: https://rubygems.org
|
|
123
|
+
homepage_uri: https://github.com/niku/xlsxrb
|
|
124
|
+
source_code_uri: https://github.com/niku/xlsxrb
|
|
125
|
+
changelog_uri: https://github.com/niku/xlsxrb/blob/main/CHANGELOG.md
|
|
126
|
+
rubygems_mfa_required: 'true'
|
|
127
|
+
rdoc_options: []
|
|
128
|
+
require_paths:
|
|
129
|
+
- lib
|
|
130
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
131
|
+
requirements:
|
|
132
|
+
- - ">="
|
|
133
|
+
- !ruby/object:Gem::Version
|
|
134
|
+
version: 4.0.0
|
|
135
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
136
|
+
requirements:
|
|
137
|
+
- - ">="
|
|
138
|
+
- !ruby/object:Gem::Version
|
|
139
|
+
version: '0'
|
|
140
|
+
requirements: []
|
|
141
|
+
rubygems_version: 4.0.10
|
|
142
|
+
specification_version: 4
|
|
143
|
+
summary: A streaming-capable, fast, low-memory XLSX reader/writer.
|
|
144
|
+
test_files: []
|