docx_report 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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: []