csv_plus_plus 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +1 -1
- data/bin/csv++ +13 -54
- data/lib/csv_plus_plus/cli_flag.rb +83 -0
- data/lib/csv_plus_plus/color.rb +45 -11
- data/lib/csv_plus_plus/error.rb +7 -0
- data/lib/csv_plus_plus/graph.rb +0 -5
- data/lib/csv_plus_plus/language/compiler.rb +0 -1
- data/lib/csv_plus_plus/language/scope.rb +0 -2
- data/lib/csv_plus_plus/language/syntax_error.rb +1 -1
- data/lib/csv_plus_plus/modifier.rb +4 -15
- data/lib/csv_plus_plus/modifier.tab.rb +367 -381
- data/lib/csv_plus_plus/options.rb +1 -0
- data/lib/csv_plus_plus/version.rb +1 -1
- data/lib/csv_plus_plus/writer/excel.rb +15 -2
- data/lib/csv_plus_plus/writer/google_sheet_builder.rb +12 -31
- data/lib/csv_plus_plus/writer/google_sheet_modifier.rb +56 -0
- data/lib/csv_plus_plus/writer/google_sheets.rb +4 -4
- data/lib/csv_plus_plus/writer/rubyxl_builder.rb +112 -0
- data/lib/csv_plus_plus/writer/rubyxl_modifier.rb +52 -0
- data/lib/csv_plus_plus/writer.rb +2 -3
- data/lib/csv_plus_plus.rb +1 -0
- metadata +26 -15
@@ -1,12 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative './rubyxl_builder'
|
4
|
+
|
3
5
|
module CSVPlusPlus
|
4
6
|
module Writer
|
5
7
|
# A class that can output a +Template+ to an Excel file
|
6
8
|
class Excel < ::CSVPlusPlus::Writer::BaseWriter
|
7
|
-
# write
|
9
|
+
# write the +template+ to an Excel file
|
8
10
|
def write(template)
|
9
|
-
|
11
|
+
::CSVPlusPlus::Writer::RubyXLBuilder.new(
|
12
|
+
output_filename: @options.output_filename,
|
13
|
+
rows: template.rows,
|
14
|
+
sheet_name: @options.sheet_name
|
15
|
+
).write
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
def load_requires
|
21
|
+
require('rubyXL')
|
22
|
+
require('rubyXL/convenience_methods')
|
10
23
|
end
|
11
24
|
end
|
12
25
|
end
|
@@ -1,8 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative './google_sheet_modifier'
|
4
|
+
|
3
5
|
module CSVPlusPlus
|
4
6
|
module Writer
|
5
|
-
##
|
6
7
|
# Given +rows+ from a +Template+, build requests compatible with Google Sheets Ruby API
|
7
8
|
# rubocop:disable Metrics/ClassLength
|
8
9
|
class GoogleSheetBuilder
|
@@ -26,9 +27,7 @@ module CSVPlusPlus
|
|
26
27
|
::Google::Apis::SheetsV4
|
27
28
|
end
|
28
29
|
|
29
|
-
def sheets_color(color)
|
30
|
-
sheets_ns::Color.new(red: color.red, green: color.green, blue: color.blue)
|
31
|
-
end
|
30
|
+
def sheets_color(color); end
|
32
31
|
|
33
32
|
def set_extended_value_type!(extended_value, value)
|
34
33
|
v = value || ''
|
@@ -43,38 +42,20 @@ module CSVPlusPlus
|
|
43
42
|
end
|
44
43
|
end
|
45
44
|
|
46
|
-
|
47
|
-
sheets_ns::TextFormat.new(
|
48
|
-
bold: mod.formatted?('bold') || nil,
|
49
|
-
italic: mod.formatted?('italic') || nil,
|
50
|
-
strikethrough: mod.formatted?('strikethrough') || nil,
|
51
|
-
underline: mod.formatted?('underline') || nil,
|
52
|
-
|
53
|
-
font_family: mod.fontfamily,
|
54
|
-
font_size: mod.fontsize,
|
55
|
-
|
56
|
-
foreground_color: mod.fontcolor ? sheets_color(mod.fontcolor) : nil
|
57
|
-
)
|
58
|
-
end
|
59
|
-
|
60
|
-
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
|
45
|
+
# rubocop:disable Metrics/AbcSize
|
61
46
|
def build_cell_format(mod)
|
62
47
|
sheets_ns::CellFormat.new.tap do |cf|
|
63
|
-
cf.text_format =
|
48
|
+
cf.text_format = mod.text_format
|
64
49
|
|
65
|
-
|
66
|
-
cf.
|
67
|
-
cf.horizontal_alignment = 'RIGHT' if mod.aligned?('right')
|
68
|
-
cf.horizontal_alignment = 'CENTER' if mod.aligned?('center')
|
69
|
-
cf.vertical_alignment = 'TOP' if mod.aligned?('top')
|
70
|
-
cf.vertical_alignment = 'BOTTOM' if mod.aligned?('bottom')
|
50
|
+
cf.horizontal_alignment = mod.halign if mod.halign
|
51
|
+
cf.vertical_alignment = mod.valign if mod.valign
|
71
52
|
|
72
|
-
cf.background_color =
|
53
|
+
cf.background_color = mod.color if mod.color
|
73
54
|
|
74
|
-
cf.number_format =
|
55
|
+
cf.number_format = mod.numberformat if mod.numberformat
|
75
56
|
end
|
76
57
|
end
|
77
|
-
# rubocop:enable Metrics/AbcSize
|
58
|
+
# rubocop:enable Metrics/AbcSize
|
78
59
|
|
79
60
|
def grid_range_for_cell(cell)
|
80
61
|
sheets_ns::GridRange.new(
|
@@ -106,10 +87,10 @@ module CSVPlusPlus
|
|
106
87
|
end
|
107
88
|
|
108
89
|
def build_cell_data(cell)
|
109
|
-
mod = cell.modifier
|
90
|
+
mod = ::CSVPlusPlus::Writer::GoogleSheetModifier.new(cell.modifier)
|
110
91
|
|
111
92
|
sheets_ns::CellData.new.tap do |cd|
|
112
|
-
cd.user_entered_format = build_cell_format(
|
93
|
+
cd.user_entered_format = build_cell_format(mod)
|
113
94
|
cd.note = mod.note if mod.note
|
114
95
|
|
115
96
|
# XXX apply data validation
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CSVPlusPlus
|
4
|
+
module Writer
|
5
|
+
# Decorate a Modifier so it can be written to the Google Sheets API
|
6
|
+
class GoogleSheetModifier < ::SimpleDelegator
|
7
|
+
# Format the halign for Google Sheets
|
8
|
+
def halign
|
9
|
+
super&.upcase
|
10
|
+
end
|
11
|
+
|
12
|
+
# Format the valign for Google Sheets
|
13
|
+
def valign
|
14
|
+
super&.upcase
|
15
|
+
end
|
16
|
+
|
17
|
+
# Format the color for Google Sheets
|
18
|
+
def color
|
19
|
+
google_sheets_color(super) if super
|
20
|
+
end
|
21
|
+
|
22
|
+
# Format the fontcolor for Google Sheets
|
23
|
+
def fontcolor
|
24
|
+
google_sheets_color(super) if super
|
25
|
+
end
|
26
|
+
|
27
|
+
# Format the numberformat for Google Sheets
|
28
|
+
def numberformat
|
29
|
+
::Google::Apis::SheetsV4::NumberFormat.new(type: super) if super
|
30
|
+
end
|
31
|
+
|
32
|
+
# Builds a SheetsV4::TextFormat with the underlying Modifier
|
33
|
+
def text_format
|
34
|
+
::Google::Apis::SheetsV4::TextFormat.new(
|
35
|
+
bold: formatted?('bold') || nil,
|
36
|
+
italic: formatted?('italic') || nil,
|
37
|
+
strikethrough: formatted?('strikethrough') || nil,
|
38
|
+
underline: formatted?('underline') || nil,
|
39
|
+
font_family: fontfamily,
|
40
|
+
font_size: fontsize,
|
41
|
+
foreground_color: fontcolor
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def google_sheets_color(color)
|
48
|
+
::Google::Apis::SheetsV4::Color.new(
|
49
|
+
red: color.red_percent,
|
50
|
+
green: color.green_percent,
|
51
|
+
blue: color.blue_percent
|
52
|
+
)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -26,8 +26,8 @@ module CSVPlusPlus
|
|
26
26
|
def write(template)
|
27
27
|
auth!
|
28
28
|
|
29
|
-
|
30
|
-
|
29
|
+
fetch_spreadsheet!
|
30
|
+
fetch_spreadsheet_values!
|
31
31
|
|
32
32
|
create_sheet! if @options.create_if_not_exists
|
33
33
|
|
@@ -58,7 +58,7 @@ module CSVPlusPlus
|
|
58
58
|
@gs.authorization = ::Google::Auth.get_application_default(::AUTH_SCOPES)
|
59
59
|
end
|
60
60
|
|
61
|
-
def
|
61
|
+
def fetch_spreadsheet_values!
|
62
62
|
formatted_values = get_all_spreadsheet_values('FORMATTED_VALUE')
|
63
63
|
formula_values = get_all_spreadsheet_values('FORMULA')
|
64
64
|
|
@@ -94,7 +94,7 @@ module CSVPlusPlus
|
|
94
94
|
@spreadsheet.sheets.find { |s| s.properties.title.strip == @sheet_name.strip }
|
95
95
|
end
|
96
96
|
|
97
|
-
def
|
97
|
+
def fetch_spreadsheet!
|
98
98
|
@spreadsheet = @gs.get_spreadsheet(@sheet_id)
|
99
99
|
|
100
100
|
return unless @sheet_name.nil?
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './rubyxl_modifier'
|
4
|
+
|
5
|
+
module CSVPlusPlus
|
6
|
+
module Writer
|
7
|
+
# Build a RubyXL workbook formatted according to the given +rows+
|
8
|
+
class RubyXLBuilder
|
9
|
+
attr_reader :output_filename, :rows
|
10
|
+
|
11
|
+
# initialize
|
12
|
+
def initialize(output_filename:, rows:, sheet_name:)
|
13
|
+
@rows = rows
|
14
|
+
@output_filename = output_filename
|
15
|
+
@workbook = open_workbook(sheet_name)
|
16
|
+
@worksheet = @workbook[sheet_name]
|
17
|
+
end
|
18
|
+
|
19
|
+
# write the given @rows in +sheet_name+ to +@output_filename+
|
20
|
+
def write
|
21
|
+
build_workbook!
|
22
|
+
@workbook.write(@output_filename)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def build_workbook!
|
28
|
+
@rows.each_with_index do |row, x|
|
29
|
+
row.cells.each_with_index do |cell, y|
|
30
|
+
modifier = ::CSVPlusPlus::Writer::RubyXLModifier.new(cell.modifier)
|
31
|
+
|
32
|
+
@worksheet.add_cell(x, y, cell.to_csv)
|
33
|
+
format_cell!(x, y, modifier)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def do_alignments!(cell, modifier)
|
39
|
+
cell.change_horizontal_alignment(modifier.halign) if modifier.halign
|
40
|
+
cell.change_vertical_alignment(modifier.valign) if modifier.valign
|
41
|
+
end
|
42
|
+
|
43
|
+
# rubocop:disable Metrics/MethodLength
|
44
|
+
def do_borders!(cell, modifier)
|
45
|
+
return unless modifier.any_border?
|
46
|
+
|
47
|
+
color = modifier.bordercolor
|
48
|
+
weight = modifier.border_weight
|
49
|
+
|
50
|
+
if modifier.border_all?
|
51
|
+
%i[top bottom left right].each do |direction|
|
52
|
+
# TODO: I can't support a weight and a color?
|
53
|
+
cell.change_border(direction, color || weight)
|
54
|
+
end
|
55
|
+
else
|
56
|
+
modifier.borders.each do |direction|
|
57
|
+
cell.change_border(direction, color || weight)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
# rubocop:enable Metrics/MethodLength
|
62
|
+
|
63
|
+
def do_fill!(cell, modifier)
|
64
|
+
cell.change_fill(modifier.color.to_hex) if modifier.color
|
65
|
+
end
|
66
|
+
|
67
|
+
def do_formats!(cell, modifier)
|
68
|
+
cell.change_font_bold(true) if modifier.formatted?('bold')
|
69
|
+
cell.change_font_italics(true) if modifier.formatted?('italic')
|
70
|
+
cell.change_font_underline(true) if modifier.formatted?('underline')
|
71
|
+
cell.change_font_strikethrough(true) if modifier.formatted?('strikethrough')
|
72
|
+
end
|
73
|
+
|
74
|
+
def do_fonts!(cell, modifier)
|
75
|
+
cell.change_font_color(modifier.fontcolor.to_hex) if modifier.fontcolor
|
76
|
+
cell.change_font_name(modifier.fontfamily) if modifier.fontfamily
|
77
|
+
cell.change_font_size(modifier.fontsize) if modifier.fontsize
|
78
|
+
end
|
79
|
+
|
80
|
+
def do_number_formats!(cell, modifier)
|
81
|
+
return unless modifier.numberformat
|
82
|
+
|
83
|
+
cell.set_number_format(modifier.number_format_code)
|
84
|
+
# TODO: this is annoying... we have to set the contents with the correct type of object
|
85
|
+
cell.change_contents(cell.value)
|
86
|
+
end
|
87
|
+
|
88
|
+
def format_cell!(row_index, cell_index, modifier)
|
89
|
+
@worksheet.sheet_data[row_index][cell_index].tap do |cell|
|
90
|
+
do_alignments!(cell, modifier)
|
91
|
+
do_borders!(cell, modifier)
|
92
|
+
do_fill!(cell, modifier)
|
93
|
+
do_fonts!(cell, modifier)
|
94
|
+
do_formats!(cell, modifier)
|
95
|
+
do_number_formats!(cell, modifier)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def open_workbook(sheet_name)
|
100
|
+
if ::File.exist?(@output_filename)
|
101
|
+
::RubyXL::Parser.parse(@output_filename).tap do |workbook|
|
102
|
+
workbook.add_worksheet(sheet_name) unless workbook[sheet_name]
|
103
|
+
end
|
104
|
+
else
|
105
|
+
::RubyXL::Workbook.new.tap do |workbook|
|
106
|
+
workbook.worksheets[0].sheet_name = sheet_name
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CSVPlusPlus
|
4
|
+
# Writer
|
5
|
+
module Writer
|
6
|
+
# Build a RubyXL-decorated Modifier class adds some support for Excel
|
7
|
+
class RubyXLModifier < ::SimpleDelegator
|
8
|
+
# https://www.rubydoc.info/gems/rubyXL/RubyXL/NumberFormats
|
9
|
+
# https://support.microsoft.com/en-us/office/number-format-codes-5026bbd6-04bc-48cd-bf33-80f18b4eae68
|
10
|
+
NUM_FMT_IDS = {
|
11
|
+
currency: 5,
|
12
|
+
date: 14,
|
13
|
+
date_time: 22,
|
14
|
+
number: 1,
|
15
|
+
percent: 9,
|
16
|
+
text: 49,
|
17
|
+
time: 21,
|
18
|
+
scientific: 48
|
19
|
+
}.freeze
|
20
|
+
private_constant :NUM_FMT_IDS
|
21
|
+
|
22
|
+
# https://www.rubydoc.info/gems/rubyXL/2.3.0/RubyXL
|
23
|
+
# ST_BorderStyle = %w{ none thin medium dashed dotted thick double hair mediumDashed dashDot mediumDashDot
|
24
|
+
# dashDotDot slantDashDot }
|
25
|
+
BORDER_STYLES = {
|
26
|
+
dashed: 'dashed',
|
27
|
+
dotted: 'dotted',
|
28
|
+
double: 'double',
|
29
|
+
solid: 'thin',
|
30
|
+
solid_medium: 'medium',
|
31
|
+
solid_thick: 'thick'
|
32
|
+
}.freeze
|
33
|
+
private_constant :BORDER_STYLES
|
34
|
+
|
35
|
+
# The excel-specific number format code
|
36
|
+
def number_format_code
|
37
|
+
::RubyXL::NumberFormats::DEFAULT_NUMBER_FORMATS.find_by_format_id(
|
38
|
+
# rubocop:disable Lint/ConstantResolution
|
39
|
+
NUM_FMT_IDS[numberformat.to_sym]
|
40
|
+
# rubocop:enable Lint/ConstantResolution
|
41
|
+
).format_code
|
42
|
+
end
|
43
|
+
|
44
|
+
# The excel-specific border weight
|
45
|
+
def border_weight
|
46
|
+
# rubocop:disable Lint/ConstantResolution
|
47
|
+
BORDER_STYLES[borderstyle.to_sym]
|
48
|
+
# rubocop:enable Lint/ConstantResolution
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/csv_plus_plus/writer.rb
CHANGED
@@ -7,7 +7,6 @@ require_relative './writer/google_sheets'
|
|
7
7
|
require_relative './writer/open_document'
|
8
8
|
|
9
9
|
module CSVPlusPlus
|
10
|
-
##
|
11
10
|
# Various strategies for writing to various formats (excel, google sheets, CSV, OpenDocument)
|
12
11
|
module Writer
|
13
12
|
# Return an instance of a writer depending on the given +options+
|
@@ -17,8 +16,8 @@ module CSVPlusPlus
|
|
17
16
|
case options.output_filename
|
18
17
|
when /\.csv$/ then ::CSVPlusPlus::Writer::CSV.new(options)
|
19
18
|
when /\.ods$/ then ::CSVPlusPlus::Writer::OpenDocument.new(options)
|
20
|
-
when /\.
|
21
|
-
else raise(::
|
19
|
+
when /\.xl(sx|sm|tx|tm)$/ then ::CSVPlusPlus::Writer::Excel.new(options)
|
20
|
+
else raise(::CSVPlusPlus::Error, "Unsupported file extension: #{options.output_filename}")
|
22
21
|
end
|
23
22
|
end
|
24
23
|
end
|
data/lib/csv_plus_plus.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: csv_plus_plus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Patrick Carroll
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-02-
|
11
|
+
date: 2023-02-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: google-apis-sheets_v4
|
@@ -39,61 +39,61 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.3'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: rubyXL
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
48
|
-
type: :
|
47
|
+
version: '3.4'
|
48
|
+
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '3.4'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: bundler
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '2'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '2'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: rake
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '13'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '13'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: rubocop
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '1.4'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
96
|
+
version: '1.4'
|
97
97
|
description: "A programming language built on top of CSV. You can define functions
|
98
98
|
and variables to use in your spreadsheet, \nthen compile it to Excel, CSV, Google
|
99
99
|
Sheets, etc.\n"
|
@@ -108,8 +108,10 @@ files:
|
|
108
108
|
- bin/csv++
|
109
109
|
- lib/csv_plus_plus.rb
|
110
110
|
- lib/csv_plus_plus/cell.rb
|
111
|
+
- lib/csv_plus_plus/cli_flag.rb
|
111
112
|
- lib/csv_plus_plus/code_section.rb
|
112
113
|
- lib/csv_plus_plus/color.rb
|
114
|
+
- lib/csv_plus_plus/error.rb
|
113
115
|
- lib/csv_plus_plus/expand.rb
|
114
116
|
- lib/csv_plus_plus/google_options.rb
|
115
117
|
- lib/csv_plus_plus/graph.rb
|
@@ -144,13 +146,22 @@ files:
|
|
144
146
|
- lib/csv_plus_plus/writer/csv.rb
|
145
147
|
- lib/csv_plus_plus/writer/excel.rb
|
146
148
|
- lib/csv_plus_plus/writer/google_sheet_builder.rb
|
149
|
+
- lib/csv_plus_plus/writer/google_sheet_modifier.rb
|
147
150
|
- lib/csv_plus_plus/writer/google_sheets.rb
|
148
151
|
- lib/csv_plus_plus/writer/open_document.rb
|
152
|
+
- lib/csv_plus_plus/writer/rubyxl_builder.rb
|
153
|
+
- lib/csv_plus_plus/writer/rubyxl_modifier.rb
|
149
154
|
homepage: https://github.com/patrickomatic/csv-plus-plus
|
150
155
|
licenses:
|
151
156
|
- MIT
|
152
157
|
metadata:
|
153
158
|
rubygems_mfa_required: 'true'
|
159
|
+
bug_tracker_uri: https://github.com/patrickomatic/csv-plus-plus/issues
|
160
|
+
documentation_uri: https://www.rubydoc.info/gems/csv_plus_plus/
|
161
|
+
github_repo: git://github.com/patrickomatic/csv_plus_plus
|
162
|
+
homepage_uri: https://github.com/patrickomatic/csv_plus_plus
|
163
|
+
source_code_uri: https://github.com/patrickomatic/csv_plus_plus
|
164
|
+
changelog_uri: https://github.com/patrickomatic/csv_plus_plus/blob/main/CHANGELOG.md
|
154
165
|
post_install_message:
|
155
166
|
rdoc_options: []
|
156
167
|
require_paths:
|