docx_report 0.0.4
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/lib/docx_report.rb +11 -0
- data/lib/docx_report/document.rb +54 -0
- data/lib/docx_report/parser.rb +62 -0
- data/lib/docx_report/record.rb +13 -0
- data/lib/docx_report/report.rb +39 -0
- data/lib/docx_report/table.rb +38 -0
- metadata +79 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ab70cd0d8827c7a3041f074932345bf11caa7686
|
4
|
+
data.tar.gz: bf99859695067c5eff160c2f57972a6f7ca2a3c0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 577280cb7c9f90409b49a2d77744a8265a5e040dc060c59b2d1c20bd3e835548af1b3555f41a3ba31ec03782041f0436394f280bcdd2f5c00856a83880dc8ebe
|
7
|
+
data.tar.gz: de34a65eca9cccc643ba842e33316ce6fe37bee1da8d768f22062645e95ff2f249dbbdae9e586e3e9cdafeef601869ac31436af567cc938765e482fb98094c1d
|
data/lib/docx_report.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'docx_report/report'
|
2
|
+
require 'docx_report/document'
|
3
|
+
require 'docx_report/parser'
|
4
|
+
require 'docx_report/table'
|
5
|
+
require 'docx_report/record'
|
6
|
+
|
7
|
+
module DocxReport
|
8
|
+
def self.create_docx_report(template_path)
|
9
|
+
Report.new template_path
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'zip'
|
2
|
+
require 'nokogiri'
|
3
|
+
|
4
|
+
module DocxReport
|
5
|
+
class Document
|
6
|
+
attr_reader :template_path, :files
|
7
|
+
|
8
|
+
def initialize(template_path)
|
9
|
+
@template_path = template_path
|
10
|
+
zip = Zip::File.open(template_path)
|
11
|
+
@files = load_files zip
|
12
|
+
zip.close
|
13
|
+
end
|
14
|
+
|
15
|
+
def save(output_path)
|
16
|
+
zip = Zip::File.open @template_path
|
17
|
+
Zip::OutputStream.open(output_path) do |output|
|
18
|
+
zip.each do |entry|
|
19
|
+
output.put_next_entry entry.name
|
20
|
+
if @files.keys.include? entry.name
|
21
|
+
output.write @files[entry.name].to_xml
|
22
|
+
else
|
23
|
+
output.write zip.read(entry.name)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
zip.close()
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def content_types_xpath
|
33
|
+
"//*[@ContentType = '#{CONTENT_TYPES.join("' or @ContentType='")}']"
|
34
|
+
end
|
35
|
+
|
36
|
+
def load_files(zip)
|
37
|
+
@files = {}
|
38
|
+
content_type_element = Nokogiri::XML zip.read(CONTENT_TYPE_NAME)
|
39
|
+
content_type_element.xpath(content_types_xpath).each do |e|
|
40
|
+
filename = e['PartName'][1..-1]
|
41
|
+
@files[filename] = Nokogiri::XML zip.read(filename)
|
42
|
+
end
|
43
|
+
@files
|
44
|
+
end
|
45
|
+
|
46
|
+
CONTENT_TYPE_NAME = '[Content_Types].xml'.freeze
|
47
|
+
|
48
|
+
CONTENT_TYPES = [
|
49
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml',
|
50
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml',
|
51
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml'
|
52
|
+
].freeze
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module DocxReport
|
4
|
+
class Parser
|
5
|
+
def initialize(document)
|
6
|
+
@document = document
|
7
|
+
end
|
8
|
+
|
9
|
+
def replace_all_fields(fields)
|
10
|
+
@document.files.values.each do |xml_element|
|
11
|
+
replace_element_fields(fields, xml_element)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def fill_all_tables(tables)
|
16
|
+
@document.files.values.each do |xml_element|
|
17
|
+
fill_element_tables(tables, xml_element)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def search_for_text(name, parent_element)
|
24
|
+
parent_element.xpath(".//*[contains(text(), '#{name}')]")
|
25
|
+
end
|
26
|
+
|
27
|
+
def replace_element_fields(fields, parent_element)
|
28
|
+
fields.each do |key, value|
|
29
|
+
search_for_text(key, parent_element).map do |element|
|
30
|
+
element.content = element.content.gsub key, value
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def find_table(name, parent_element)
|
36
|
+
parent_element.xpath(".//w:tbl[//w:tblCaption[@w:val='#{name}']][1]").first
|
37
|
+
end
|
38
|
+
|
39
|
+
def find_row(table_element, row_number)
|
40
|
+
table_element.xpath(".//w:tr[#{row_number}]").first
|
41
|
+
end
|
42
|
+
|
43
|
+
def fill_element_tables(tables, parent_element)
|
44
|
+
tables.each do |table|
|
45
|
+
tbl = find_table table.name, parent_element
|
46
|
+
if tbl
|
47
|
+
row_number = table.has_header ? 2 : 1
|
48
|
+
tbl_row = find_row tbl, row_number
|
49
|
+
|
50
|
+
if tbl_row
|
51
|
+
table.records.each do |record|
|
52
|
+
new_row = tbl_row.dup
|
53
|
+
tbl_row.add_previous_sibling new_row
|
54
|
+
replace_element_fields record.fields, new_row
|
55
|
+
end
|
56
|
+
tbl_row.remove
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
module DocxReport
|
4
|
+
class Report
|
5
|
+
attr_reader :fields, :tables
|
6
|
+
|
7
|
+
def initialize(template_path)
|
8
|
+
@template_path = template_path
|
9
|
+
@fields = {}
|
10
|
+
@tables = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_field(name, value)
|
14
|
+
@fields["{@#{name}}"] = value
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_table(name, collection = nil, has_header = false)
|
18
|
+
table = Table.new name, has_header
|
19
|
+
@tables << table
|
20
|
+
yield table
|
21
|
+
table.load_records collection if collection
|
22
|
+
end
|
23
|
+
|
24
|
+
def generate_docx(filename = nil, template_path = nil)
|
25
|
+
doc = Document.new template_path || @template_path
|
26
|
+
parser = Parser.new doc
|
27
|
+
parser.fill_all_tables @tables
|
28
|
+
parser.replace_all_fields @fields
|
29
|
+
temp = Tempfile.new('') if filename.nil?
|
30
|
+
docx_path = filename || temp.path
|
31
|
+
begin
|
32
|
+
doc.save docx_path
|
33
|
+
File.read docx_path if filename.nil?
|
34
|
+
ensure
|
35
|
+
temp.close! if temp
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module DocxReport
|
2
|
+
class Table
|
3
|
+
attr_accessor :name, :has_header, :records
|
4
|
+
|
5
|
+
def initialize(name, has_header = false)
|
6
|
+
@name = name
|
7
|
+
@has_header = has_header
|
8
|
+
@records = []
|
9
|
+
@fields = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def new_record
|
13
|
+
new_record = Record.new
|
14
|
+
records << new_record
|
15
|
+
new_record
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_field(name, mapped_field)
|
19
|
+
@fields << { name: name, mapped_field: mapped_field }
|
20
|
+
end
|
21
|
+
|
22
|
+
def load_records(collection)
|
23
|
+
collection.each do |item|
|
24
|
+
record = new_record
|
25
|
+
@fields.each do |field|
|
26
|
+
record.add_field field[:name],
|
27
|
+
mapped_value(item, field[:mapped_field])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def mapped_value(item, field_name)
|
35
|
+
item.is_a?(Hash) ? item[field_name] : item.send(field_name)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: docx_report
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ahmed Abudaqqa
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-03-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: nokogiri
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rubyzip
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.2'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.2'
|
41
|
+
description: |-
|
42
|
+
docx_report is a light weight gem that generates docx files
|
43
|
+
by replacing strings on previously created .docx file
|
44
|
+
email: ahmed@abudaqqa.com
|
45
|
+
executables: []
|
46
|
+
extensions: []
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- lib/docx_report.rb
|
50
|
+
- lib/docx_report/document.rb
|
51
|
+
- lib/docx_report/parser.rb
|
52
|
+
- lib/docx_report/record.rb
|
53
|
+
- lib/docx_report/report.rb
|
54
|
+
- lib/docx_report/table.rb
|
55
|
+
homepage: https://github.com/abudaqqa/docx_report
|
56
|
+
licenses:
|
57
|
+
- MIT
|
58
|
+
metadata: {}
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
requirements: []
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 2.4.5.1
|
76
|
+
signing_key:
|
77
|
+
specification_version: 4
|
78
|
+
summary: docx_report generate docx files based on previously created .docx file
|
79
|
+
test_files: []
|