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 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
@@ -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,13 @@
1
+ module DocxReport
2
+ class Record
3
+ attr_accessor :fields
4
+
5
+ def initialize
6
+ @fields = {}
7
+ end
8
+
9
+ def add_field(name, value)
10
+ fields["{@#{name}}"] = value
11
+ end
12
+ end
13
+ 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: []