-
Notifications
You must be signed in to change notification settings - Fork 2
/
docx_appender.rb
executable file
·243 lines (184 loc) · 5.32 KB
/
docx_appender.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
#!/usr/bin/env ruby
##########################################################
###
## File: docx_appender.rb
## Desc: Appends a list of docx files into one docx file
## By: Dewayne VanHoozer ([email protected])
#
require 'amazing_print' # Pretty print Ruby objects with proper indentation and colors
require 'pp'
require 'pathname' # STDLIB
require 'fileutils' # STDLIB
require 'docx' # a ruby library/gem for interacting with .docx files
require 'docx_helpers'
include DocxHelpers
me = Pathname.new(__FILE__).realpath
my_dir = me.parent
my_name = me.basename.to_s
$options = {
verbose: false,
debug: false,
file_sep: false,
no_blanks: false,
publication: :ddg,
docx_files: []
}
def verbose?
$options[:verbose]
end
def debug?
$options[:debug]
end
def file_sep?
$options[:file_sep]
end
def remove_blanks?
$options[:no_blanks]
end
usage = <<EOS
Appends a list of docx files into one docx file
Usage: #{my_name} [options] docx_files|directory
Where:
options Do This
-h or --help Display this message
-v or --verbose Display progress
--no-sep Do not add the 'FileName:' seperater paragraph
--no-blanks Do not copy empty paragraphs
docx_files|directory List of *.docx files
or a single directory
NOTE:
The output docx file will be automatically named for
the parent directory of the first file in the list.
LIMITATION:
The style definitions, bookmarks, references, etc. are not
transfered into the new document. If a paragraph style was
not defined in the first document, then those paragraphs in
subsequent documents will be treated as Normal.
EOS
errors = []
if ARGV.empty? or
ARGV.include? '-h' or
ARGV.include?'--help'
puts usage
exit
end
%w[ -v --verbose ].each do |param|
if ARGV.include?(param)
$options[:verbose] = true
i = ARGV.index param
ARGV[i] = nil
end
end
if ARGV.include?('--no-sep')
$options[:file_sep] = false
i = ARGV.index '--no-sep'
ARGV[i] = nil
end
if ARGV.include?('--no-blanks')
$options[:no_blanks] = false
i = ARGV.index '--no-blanks'
ARGV[i] = nil
end
ARGV.compact!
if ARGV.empty?
puts usage
exit
end
if 1 == ARGV.size
source_directory = Pathname.new ARGV.first
if source_directory.exist?
source_directory = source_directory.realpath
$options[:docx_files] = source_directory.children
source_directory.children.each do |c|
if c.file? and
'.docx' == c.extname.downcase
$options[:docx_files] << c unless c.basename.to_s.downcase.start_with?('backup')
end
end
errors << "There are no *.docx files in #{source_directory.basename}" if $options[:docx_files].empty?
else
errors << "directory is invalid: #{source_directory}"
end
else
$options[:docx_files] = ARGV.map { |a| Pathname.new(a)}
end
$options[:docx_files].each do | a_path |
unless a_path.exist?
errors << "Does not exist: #{a_path}"
else
if a_path.directory?
errors << "Not a file: #{a_path}"
else
unless '.docx' == a_path.extname.downcase
errors << "Not an MS Word *.docx: #{a_path}"
end
end
end
end
unless errors.empty?
puts
puts "Correct the following errors and try again:"
puts
errors.each do |e|
puts "\t#{e}"
end
puts
exit(1)
end
$options[:docx_files].map! {|a_path| a_path.realpath}
#FIXME: not using pub_styles_path
pub_styles_path = my_dir +
"docx_templates" +
$options[:publication].to_s.upcase +
"#{$options[:publication]}_styles.docx"
ap pub_styles_path if debug?
######################################################
# Local methods
######################################################
# Main
at_exit do
puts
puts "Done."
puts
end
$options[:docx_files].sort!
ap $options if debug?
out_dir = $options[:docx_files].first.parent
docx_out_path = out_dir + "#{out_dir.basename}.docx"
FileUtils.cp(pub_styles_path, docx_out_path) # SMELL: don't think the styles are coming from here
sleep(5) if debug?
docx_out = Docx::Document.open($options[:docx_files].first) # SMELL: all styles from here ??
# Do the first file to get the proper styles established
# FIXME: this doesn't work; its not using the correct starting out file
if file_sep?
para = docx_out.paragraphs.first.copy
para.insert_after docx_out.paragraphs.first
set_paragraph_style_name(docx_out.paragraphs.first, 'FileName')
docx_out.paragraphs.first.text = "FileName: #{$options[:docx_files].first.basename}"
end
$options[:docx_files].shift
# Do the rest of the files
$options[:docx_files].each do |c|
next if c == docx_out_path
puts "Appending #{c.basename} ..." if verbose?
docx = Docx::Document.open(c)
if file_sep?
para = docx.paragraphs.first.copy
set_paragraph_style_name(para, 'FileName')
para.text = "FileName: #{c.basename}"
para.insert_after docx_out.paragraphs.last
else
para = docx.paragraphs.first.copy
para.text = " "
para.insert_after docx_out.paragraphs.last
end
docx.paragraphs.size.times do |x|
para = docx.paragraphs[x].copy
if remove_blanks?
a_text = para.text.chomp.strip
next if a_text.empty?
end
para.insert_after docx_out.paragraphs.last
end
end
docx_out.save(docx_out_path)