Class: MyDocx

Inherits:
Object
  • Object
show all
Defined in:
lib/simple_docx_generator/mydocx.rb

Overview

クラス/MyDocx

docxを扱うクラスです
主な機能は次のとおりです
* テンプレートファイルの場所を指定してインスタンス化します
* keysメソッドでテンプレートファイルに含まれる変数(以下、テンプレートファイルで使う変数を単に変数といいます)を取得します
* setメソッドで変数に値を代入することができます
* generateメソッドでdocxファイルを生成します

Constant Summary collapse

VAR_REGEX =

変数を定義する正規表現

変数の定義

  • @@で始まり、@@で終わる

  • 半角アルファベットの大文字・小文字またはアンダーバーで始まる

  • 2文字目以降は半角アルファベットの大文字・小文字アンダーバーのほかに数字とピリオドを使うことができる

  • 最初のピリオドから次のピリオドないし最後の@@までの文字列をプロパティという

    @@hello.text@@

    • .checkboxプロパティ 値をStringの“1”に指定すると☑に置換えます。それ以外の値は☐に置換えます

    • .textプロパティ 改行も含めて再現します

Regexp.new('@@[a-zA-Z_][a-zA-Z0-9_.]+?@@')

Instance Method Summary collapse

Constructor Details

#initialize(path_to_template) ⇒ MyDocx

initialize

インスタンスの初期化

Param

path_to_templateはテンプレートファイルの場所を指定します

テンプレートファイルに半角スペースなどを含んでいると生成されたdocxにエラーが出ます



30
31
32
33
34
35
36
# File 'lib/simple_docx_generator/mydocx.rb', line 30

def initialize(path_to_template)
  @keys_index = {}
  @filename = File.basename(path_to_template)
  @dir = File.dirname(path_to_template)
  set_document_xml(path_to_template)
  set_keys_index
end

Instance Method Details

#all_textObject

all_text

すべてのテキストをArrayで返します。今のところヘッダー・フッターは未対応です。デバッグ用。



70
71
72
73
74
# File 'lib/simple_docx_generator/mydocx.rb', line 70

def all_text
  @document_xml.xpath("//w:t").map do |t_node|
    t_node.content
  end
end

#document_xmlObject



114
115
116
# File 'lib/simple_docx_generator/mydocx.rb', line 114

def document_xml
  @document_xml.to_xml
end

#generate(filename = 'output_' + @filename) ⇒ Object

generate

@document_xmlを使ってdocxファイルを生成します docxファイルはテンプレートファイルと同じディレクトリに生成されます もし同じファイル名のファイルが存在していた場合はそのファイルを上書きします

Param

filenameにdocx拡張子をつけた名前がファイル名となります

もしfilenameを指定しない場合はoutput_元のファイル名.docxというファイルになります Return: パス付きのfilenameを値として返します



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/simple_docx_generator/mydocx.rb', line 96

def generate(filename = 'output_' + @filename)
  File.delete(filename) if File.exist?(filename)
  buffer = Zip::OutputStream.write_buffer(::StringIO.new('')) do |out|
    Zip::InputStream.open(File.join(@dir, @filename)) do |input|
      while (entry = input.get_next_entry)
        out.put_next_entry(entry.name)
        if entry.name == 'word/document.xml'
          out.write @document_xml.to_xml
        else
          out.write input.read
        end
      end
    end
  end
  File.open(File.join(@dir, filename), 'wb') {|f| f.write(buffer.string)}
  File.join @dir, filename
end

#keysObject

keys

変数の一覧をArrayで返します

Return

変数の一覧をArrayで返します



55
56
57
58
59
# File 'lib/simple_docx_generator/mydocx.rb', line 55

def keys
  @keys_index.map do |key, value|
    key
  end
end

#keys_indexObject

keys_index

変数と変数が含まれている場所です

Return

形式は変数をkey、対応する場所のArray(同じ変数がテンプレートファイル内に複数存在する可能性があります)をvalueとしたハッシュ形式です。デバッグ用。



64
65
66
# File 'lib/simple_docx_generator/mydocx.rb', line 64

def keys_index
  @keys_index
end

#set(key, value = '') ⇒ Object

set

変数に値を代入します

Params

key, valueともにString valueを指定しない場合は”になります

Return

setに成功したらtrue、失敗したらfalseが返ります

典型的にはkeyが存在しない場合を想定しています



43
44
45
46
47
48
49
50
# File 'lib/simple_docx_generator/mydocx.rb', line 43

def set(key, value = '')
  value = set_checkbox_value(key, value)
  if key.gsub(/@@/, '').split('.')[1] == 'text'
    replace_br(key, value)
  else
    replace(key, value)
  end
end

#to_html(class_name = '') ⇒ Object

to_html

ydocxというパーサーを介して<div>タグで囲んだhtmlを返します オプションで<div>タグのclass名を指定できます



79
80
81
82
83
84
85
86
87
# File 'lib/simple_docx_generator/mydocx.rb', line 79

def to_html(class_name='')
  ydocx = YDocx::Document.open File.join(@dir, @filename)
  html = Nokogiri::HTML ydocx.to_html
  nodes = html.xpath("//body").children
  myhtml = Nokogiri::HTML::DocumentFragment.parse "<div></div>"
  myhtml.child['class'] = class_name unless class_name.empty?
  myhtml.child << nodes
  myhtml.to_s
end

#update_xml(xml_text) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/simple_docx_generator/mydocx.rb', line 118

def update_xml xml_text
  buffer = Zip::OutputStream.write_buffer(::StringIO.new('')) do |out|
    Zip::InputStream.open(File.join(@dir, @filename)) do |input|
      while (entry = input.get_next_entry)
        out.put_next_entry(entry.name)
        if entry.name == 'word/document.xml'
          out.write xml_text
        else
          out.write input.read
        end
      end
    end
  end
  File.open(File.join(@dir, @filename), 'wb') {|f| f.write(buffer.string)}
  initialize File.join(@dir, @filename)
end