mymatrix 0.0.1
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.
- data/.gemtest +0 -0
- data/History.txt +4 -0
- data/Manifest.txt +11 -0
- data/PostInstall.txt +7 -0
- data/README.rdoc +50 -0
- data/Rakefile +26 -0
- data/lib/mymatrix.rb +1235 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/test/test_helper.rb +3 -0
- data/test/test_mymatrix.rb +11 -0
- metadata +98 -0
data/.gemtest
ADDED
File without changes
|
data/History.txt
ADDED
data/Manifest.txt
ADDED
data/PostInstall.txt
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
= mymatrix
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
mymatrix is a handling library for MS Excel and csv/tsv text.
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
Support filetypes: .xls, .tsv, .csv
|
12
|
+
|
13
|
+
|
14
|
+
== SYNOPSIS:
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
== REQUIREMENTS:
|
19
|
+
|
20
|
+
Support ruby versions are:
|
21
|
+
ruby 1.8.7
|
22
|
+
ruby 1.9.2 or higher
|
23
|
+
|
24
|
+
== INSTALL:
|
25
|
+
gem install mymatrix
|
26
|
+
|
27
|
+
== LICENSE:
|
28
|
+
|
29
|
+
(The MIT License)
|
30
|
+
|
31
|
+
Copyright (c) 2012 zucay
|
32
|
+
|
33
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
34
|
+
a copy of this software and associated documentation files (the
|
35
|
+
'Software'), to deal in the Software without restriction, including
|
36
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
37
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
38
|
+
permit persons to whom the Software is furnished to do so, subject to
|
39
|
+
the following conditions:
|
40
|
+
|
41
|
+
The above copyright notice and this permission notice shall be
|
42
|
+
included in all copies or substantial portions of the Software.
|
43
|
+
|
44
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
45
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
46
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
47
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
48
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
49
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
50
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
gem 'hoe', '>= 2.1.0'
|
3
|
+
require 'hoe'
|
4
|
+
require 'fileutils'
|
5
|
+
require './lib/mymatrix'
|
6
|
+
|
7
|
+
Hoe.plugin :newgem
|
8
|
+
# Hoe.plugin :website
|
9
|
+
# Hoe.plugin :cucumberfeatures
|
10
|
+
|
11
|
+
# Generate all the Rake tasks
|
12
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
13
|
+
$hoe = Hoe.spec 'mymatrix' do
|
14
|
+
self.developer 'zucay', 'yukihico@gmail.com'
|
15
|
+
|
16
|
+
self.rubyforge_name = self.name # TODO this is default value
|
17
|
+
# self.extra_deps = [['activesupport','>= 2.0.2']]
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'newgem/tasks'
|
22
|
+
Dir['tasks/**/*.rake'].each { |t| load t }
|
23
|
+
|
24
|
+
# TODO - want other tests/tasks run by default? Add them to the list
|
25
|
+
# remove_task :default
|
26
|
+
# task :default => [:spec, :features]
|
data/lib/mymatrix.rb
ADDED
@@ -0,0 +1,1235 @@
|
|
1
|
+
#!/usr/bin/ruby -Ku
|
2
|
+
# -*- encoding: utf-8 -*-
|
3
|
+
|
4
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
5
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
6
|
+
|
7
|
+
require 'rubygems'
|
8
|
+
require 'spreadsheet'
|
9
|
+
require 'nkf'
|
10
|
+
require 'logger'
|
11
|
+
require 'pp'
|
12
|
+
require 'enumerable_ex' #verbose_each
|
13
|
+
|
14
|
+
if(RUBY_VERSION =~ /1\.[^9]/)
|
15
|
+
$KCODE='UTF8'
|
16
|
+
end
|
17
|
+
|
18
|
+
class MyMatrix
|
19
|
+
VERSION = '0.0.1'
|
20
|
+
|
21
|
+
attr_accessor :file, :internal_lf, :mx
|
22
|
+
include Enumerable
|
23
|
+
#to_t()の際のセパレータ。
|
24
|
+
SEPARATOR = "\t"
|
25
|
+
|
26
|
+
# コンストラクタ
|
27
|
+
# ====Args
|
28
|
+
# _file_ :: オープンするファイル。
|
29
|
+
# ====Return
|
30
|
+
# 生成されたMyMatrixオブジェクト
|
31
|
+
def initialize(file=nil, opts={})
|
32
|
+
#platform check
|
33
|
+
if(RUBY_PLATFORM.downcase =~ /mswin(?!ce)|mingw|cygwin|bccwin/)
|
34
|
+
$mymatrix_filesystem = 's'
|
35
|
+
elsif(RUBY_PLATFORM.downcase =~ /darwin/)
|
36
|
+
$mymatrix_filesystem = 'm'
|
37
|
+
elsif(RUBY_PLATFORM.downcase =~ /linux/)
|
38
|
+
$mymatrix_filesystem = 'u'
|
39
|
+
else
|
40
|
+
$mymatrix_filesystem = 'u'
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
#内部改行コード。
|
46
|
+
@internal_lf = '<br>'
|
47
|
+
rnd = rand(9999)
|
48
|
+
i = 0
|
49
|
+
begin
|
50
|
+
@log = Logger.new("MyMatrix_ERR_#{i}.log")
|
51
|
+
rescue
|
52
|
+
i += 1
|
53
|
+
retry
|
54
|
+
end
|
55
|
+
@log.level = Logger::DEBUG
|
56
|
+
@file = file
|
57
|
+
|
58
|
+
@mx = []
|
59
|
+
if(@file =~ /\.xls$/)
|
60
|
+
@mx = makeMatrixFromXLS(@file, opts)
|
61
|
+
elsif(@file =~ /(\.tsv|\.txt|\.TSV|\.TXT)/)
|
62
|
+
@mx = makeMatrixFromTSV(@file, opts)
|
63
|
+
elsif(@file =~ /(\.csv|\.CSV)/)
|
64
|
+
#opts[:sep] = ','
|
65
|
+
#@mx = makeMatrixFromTSV(@file, opts)
|
66
|
+
@mx = makeMatrixFromCSV(@file, opts)
|
67
|
+
|
68
|
+
# elsif(@file =~ /\.mmx$/)
|
69
|
+
# readmx = Marshal.load(open(@file).read)
|
70
|
+
# return readmx
|
71
|
+
elsif(@file == nil)
|
72
|
+
else
|
73
|
+
#デフォルトはTSVで読み込むようにする。
|
74
|
+
@mx = makeMatrixFromTSV(@file, opts)
|
75
|
+
end
|
76
|
+
|
77
|
+
#@mxの末尾に空レコードが入っていたら、その空白を削除
|
78
|
+
while(@mx[@mx.size-1] && @mx[@mx.size-1].join == '')
|
79
|
+
@mx.pop
|
80
|
+
end
|
81
|
+
if(@mx.size == 0)
|
82
|
+
@mx = []
|
83
|
+
end
|
84
|
+
@headers = @mx.shift
|
85
|
+
registerMatrix
|
86
|
+
return self
|
87
|
+
end
|
88
|
+
|
89
|
+
# CP932を正しく扱うための変換関数
|
90
|
+
# ====Args
|
91
|
+
# _str_ :: UTF8文字列
|
92
|
+
# ====Return
|
93
|
+
# CP932の文字列
|
94
|
+
def self.tosjis(str)
|
95
|
+
str = MyMatrix.cp932ize(str)
|
96
|
+
if(RUBY_VERSION =~ /1\.[^9]/)
|
97
|
+
#-xは半角カナを全角にするのを抑止するオプション。
|
98
|
+
out = NKF.nkf('-W -x -s --cp932', str)
|
99
|
+
else
|
100
|
+
out = str.encode("Windows-31J")
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
return out
|
105
|
+
end
|
106
|
+
# 外部ファイルエンコード(CP932)を内部エンコード(UTF8)に変換する
|
107
|
+
# ====Args
|
108
|
+
# _str_:: CP932 string
|
109
|
+
# ====Return
|
110
|
+
# UTF8 String
|
111
|
+
def self.toutf8(str)
|
112
|
+
#out = NKF.nkf('-x -w --cp932', str)
|
113
|
+
#入力がShift-jisであるとする。
|
114
|
+
out = NKF.nkf('-S -x -w --cp932', str)
|
115
|
+
return out
|
116
|
+
end
|
117
|
+
|
118
|
+
# MacOSXのファイルシステムで使われるUTF8-Mac(BOMつきUTF)に変換する
|
119
|
+
def self.toUtf8Mac(str)
|
120
|
+
out = str
|
121
|
+
return out
|
122
|
+
end
|
123
|
+
# ファイルオープン時、パス文字列のエンコードを変換してシステムに返却するためのメソッド
|
124
|
+
def encodePath(path)
|
125
|
+
case $mymatrix_filesystem
|
126
|
+
when 'u'
|
127
|
+
#utf8=>utf8なので何もしない
|
128
|
+
#path = MyMatrix.toutf8(path)
|
129
|
+
#path.encode('UTF-8')
|
130
|
+
path
|
131
|
+
when 's'
|
132
|
+
path = MyMatrix.tosjis(path)
|
133
|
+
#path.encode('Windows-31J')
|
134
|
+
when 'w'
|
135
|
+
path = MyMatrix.tosjis(path)
|
136
|
+
#path.encode('Windows-31J')
|
137
|
+
when 'm'
|
138
|
+
path = MyMatrix.toUtf8Mac(path)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
#--
|
143
|
+
#protected methods
|
144
|
+
#++
|
145
|
+
protected
|
146
|
+
# 現在のヘッダ@headersに合わせてハッシュ@headerHを生成する
|
147
|
+
# @headersを書き換えた場合に必ず実行するメソッド
|
148
|
+
def registerMatrix
|
149
|
+
@headerH = Hash.new
|
150
|
+
if(!@headers)
|
151
|
+
@headers = []
|
152
|
+
end
|
153
|
+
@headers.each_with_index do |colName, i|
|
154
|
+
@headerH[colName] = i
|
155
|
+
end
|
156
|
+
fillEmptyCell
|
157
|
+
end
|
158
|
+
|
159
|
+
# ヘッダ@headers を書き換えた場合など、@headers.sizeとrow.sizeが異なる場合にサイズを揃え
|
160
|
+
# 空文字列を入れておく。getValue()した際に必ずStringを返却するための処理。
|
161
|
+
# ====※rowを伸ばす方向のみ。@headersを短くした場合の動作は保証できない!
|
162
|
+
#
|
163
|
+
def fillEmptyCell
|
164
|
+
headerSize = getHeaders.size
|
165
|
+
@mx.each_with_index do |row, i|
|
166
|
+
if(row.size < headerSize)
|
167
|
+
(headerSize - row.size).times do |i|
|
168
|
+
row << ''
|
169
|
+
end
|
170
|
+
elsif(row.size > headerSize)
|
171
|
+
warn("row is large:#{@file} line #{i+2} / rowSize #{row.size} / headersize #{headerSize}")
|
172
|
+
#raise "rowsize error"
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
# xls読み込みメソッド
|
177
|
+
def makeMatrixFromXLS(xlsFile, opts={})
|
178
|
+
if(opts)
|
179
|
+
offset = opts[:offset]
|
180
|
+
end
|
181
|
+
offset ||= 0
|
182
|
+
|
183
|
+
out = []
|
184
|
+
#todo xlsFileがなかったら作成
|
185
|
+
encodePath(xlsFile)
|
186
|
+
xl = Spreadsheet.open(encodePath(xlsFile), 'rb')
|
187
|
+
sheet = xl.worksheet(0)
|
188
|
+
rowsize = sheet.last_row_index
|
189
|
+
(rowsize+1-offset).times do |i|
|
190
|
+
row = sheet.row(i+offset)
|
191
|
+
orow = []
|
192
|
+
row.each do |ele|
|
193
|
+
#様々な型で値が入っている。改行も入っている
|
194
|
+
if(ele.class == Float)&&(ele.to_s =~ /(\d+)\.0/)
|
195
|
+
ele = $1
|
196
|
+
end
|
197
|
+
if(ele.class == Spreadsheet::Formula)
|
198
|
+
ele = ele.value
|
199
|
+
end
|
200
|
+
if(ele == nil)
|
201
|
+
ele = ''
|
202
|
+
end
|
203
|
+
ele = ele.to_s.gsub(/\n/, '<br>')
|
204
|
+
orow << ele
|
205
|
+
end
|
206
|
+
out << orow
|
207
|
+
end
|
208
|
+
|
209
|
+
return out
|
210
|
+
end
|
211
|
+
#TSV: tab separated value 読み込みメソッド
|
212
|
+
def makeMatrixFromTSV(file, opts={:sep=>SEPARATOR, :offset=>0})
|
213
|
+
out = []
|
214
|
+
epath = encodePath(file)
|
215
|
+
if(!File.exist?(epath))
|
216
|
+
open(epath, 'w') do |fo|
|
217
|
+
fo.print("\n\n")
|
218
|
+
end
|
219
|
+
end
|
220
|
+
#fi = open(file.encode('Windows-31J'), "r:Windows-31J")
|
221
|
+
fi = open(encodePath(file), "r:Windows-31J")
|
222
|
+
if(opts[:offset])
|
223
|
+
opts[:offset].times do |i|
|
224
|
+
fi.gets
|
225
|
+
end
|
226
|
+
end
|
227
|
+
opts[:sep]||=SEPARATOR
|
228
|
+
fi.each do |line|
|
229
|
+
row = MyMatrix.toutf8(line).chomp.split(/#{opts[:sep]}/)
|
230
|
+
#「1,300台」などカンマが使われている場合、「"1,300台"」となってしまうので、カンマを無視する
|
231
|
+
newRow = []
|
232
|
+
row.each do |cell|
|
233
|
+
stri = cell.dup
|
234
|
+
stri.gsub!(/^\"(.*)\"$/, '\1')
|
235
|
+
#"
|
236
|
+
stri.gsub!(/""/, '"')
|
237
|
+
newRow << stri
|
238
|
+
end
|
239
|
+
out << newRow
|
240
|
+
end
|
241
|
+
fi.close
|
242
|
+
return out
|
243
|
+
end
|
244
|
+
|
245
|
+
#CSV読み込みメソッド
|
246
|
+
def makeMatrixFromCSV(file, opts={:offset=>0})
|
247
|
+
#1.9系ではFasterCSVを使えない
|
248
|
+
if(RUBY_VERSION =~ /1\.[^9]/)
|
249
|
+
#1.8以下の場合
|
250
|
+
require 'fastercsv'
|
251
|
+
csv = FasterCSV
|
252
|
+
else
|
253
|
+
#1.9以上の場合
|
254
|
+
require 'csv'
|
255
|
+
Encoding.default_external = 'Windows-31J'
|
256
|
+
csv = CSV
|
257
|
+
end
|
258
|
+
out = []
|
259
|
+
i= 0
|
260
|
+
syspath = encodePath(file)
|
261
|
+
csv.foreach(syspath, {:row_sep => "\r\n", :encoding => 'Shift_JIS'}) do |row|
|
262
|
+
if(opts[:offset])
|
263
|
+
if(opts[:offset] < i)
|
264
|
+
next
|
265
|
+
end
|
266
|
+
end
|
267
|
+
#「1,300台」などカンマが使われている場合、「"1,300台"」となってしまうので、カンマを無視する
|
268
|
+
newRow = []
|
269
|
+
row.each do |cell|
|
270
|
+
cell = cell.to_s
|
271
|
+
cell ||= ''
|
272
|
+
cell = MyMatrix.toutf8(cell)
|
273
|
+
#cell = cell.gsub(/^\"/, "")
|
274
|
+
#cell = cell.gsub(/\"$/, "")
|
275
|
+
#"
|
276
|
+
newRow << cell
|
277
|
+
end
|
278
|
+
out << newRow
|
279
|
+
i += 1
|
280
|
+
end
|
281
|
+
return out
|
282
|
+
end
|
283
|
+
|
284
|
+
def isEnd(row)
|
285
|
+
out = true
|
286
|
+
row.each do |cell|
|
287
|
+
if(cell != "")
|
288
|
+
out = nil
|
289
|
+
break
|
290
|
+
end
|
291
|
+
end
|
292
|
+
return out
|
293
|
+
end
|
294
|
+
|
295
|
+
public
|
296
|
+
# カラムの値を配列で返却する
|
297
|
+
def getColumn(colName)
|
298
|
+
out = []
|
299
|
+
@mx.each do |row|
|
300
|
+
begin
|
301
|
+
out << getValue(row, colName)
|
302
|
+
rescue
|
303
|
+
raise "#{colName} notfound: #{row}"
|
304
|
+
end
|
305
|
+
end
|
306
|
+
return out
|
307
|
+
end
|
308
|
+
|
309
|
+
# getColumn のエイリアスメソッド
|
310
|
+
def getValues(colName)
|
311
|
+
return getColumn(colName)
|
312
|
+
end
|
313
|
+
#カラムの値を複数指定して、多次元配列を返却するメソッド。
|
314
|
+
def getColumns(colNames)
|
315
|
+
out = []
|
316
|
+
colNames.each do |colName|
|
317
|
+
out << getColumn(colName)
|
318
|
+
end
|
319
|
+
return out
|
320
|
+
end
|
321
|
+
|
322
|
+
#
|
323
|
+
def getColumnsByMatrix(colNames)
|
324
|
+
out = MyMatrix.new
|
325
|
+
colNames.each do |colName|
|
326
|
+
col = getColumn(colName)
|
327
|
+
out.addColumn(colName, col)
|
328
|
+
end
|
329
|
+
return out
|
330
|
+
end
|
331
|
+
def val(row, str)
|
332
|
+
getValue(row, str)
|
333
|
+
end
|
334
|
+
|
335
|
+
def getValue(row, str)
|
336
|
+
out = nil
|
337
|
+
index = @headerH[str]
|
338
|
+
if(index)
|
339
|
+
out = row[index]
|
340
|
+
#お尻のセルでNULLの場合などは、nilが返却されてしまう。なので、''となるようにする。
|
341
|
+
if(!out)
|
342
|
+
out = ''
|
343
|
+
end
|
344
|
+
#参照を渡さないためdupする
|
345
|
+
out = out.dup
|
346
|
+
else
|
347
|
+
raise "header not found:#{str} file:#{@file}"
|
348
|
+
end
|
349
|
+
return out
|
350
|
+
end
|
351
|
+
alias val getValue
|
352
|
+
=begin
|
353
|
+
def getValues(row, arr)
|
354
|
+
out = []
|
355
|
+
arr.each do |ele|
|
356
|
+
out << getValue(row, ele)
|
357
|
+
end
|
358
|
+
if(out.size == 0)
|
359
|
+
out = nil
|
360
|
+
end
|
361
|
+
return out
|
362
|
+
end
|
363
|
+
=end
|
364
|
+
def setValue(row, str, value)
|
365
|
+
if(!row)
|
366
|
+
raise 'row is nil'
|
367
|
+
end
|
368
|
+
index = @headerH[str]
|
369
|
+
if(!index)
|
370
|
+
addHeaders([str])
|
371
|
+
end
|
372
|
+
#参照先の値も変更できるように、破壊メソッドを使う。row[@headerH[str]] = valueでは、参照先が切り替わってしまうので、値の置き換えにならない。
|
373
|
+
#findなどで取得したrowに対して処理を行う際に必要な変更。
|
374
|
+
if(row[@headerH[str]].class == String)
|
375
|
+
row[@headerH[str]].sub!(/^.*$/, value)
|
376
|
+
else
|
377
|
+
#raise('not string error.')
|
378
|
+
#todo 強烈なバグな気もするが、例外を回避し値を代入2010年12月15日
|
379
|
+
begin
|
380
|
+
row[@headerH[str]] = value.to_s
|
381
|
+
rescue
|
382
|
+
row[@headerH[str]] = ''
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|
386
|
+
def each
|
387
|
+
@mx.each do |row|
|
388
|
+
yield(row)
|
389
|
+
end
|
390
|
+
end
|
391
|
+
#未検証
|
392
|
+
def reverse
|
393
|
+
out = empty
|
394
|
+
|
395
|
+
@mx.reverse.each do |row|
|
396
|
+
out << row
|
397
|
+
end
|
398
|
+
return out
|
399
|
+
end
|
400
|
+
|
401
|
+
|
402
|
+
def size
|
403
|
+
return @mx.size
|
404
|
+
end
|
405
|
+
def [](i,j)
|
406
|
+
return @mx[i][j]
|
407
|
+
end
|
408
|
+
|
409
|
+
def [](i)
|
410
|
+
return @mx[i]
|
411
|
+
end
|
412
|
+
|
413
|
+
#未検証
|
414
|
+
def +(other)
|
415
|
+
out = MyipcMatrix.new
|
416
|
+
|
417
|
+
othHeaders = other.getHeaders
|
418
|
+
selHeaders = getHeaders
|
419
|
+
|
420
|
+
selHeaders.each do |header|
|
421
|
+
out.addColumn(header, getColumn(header))
|
422
|
+
end
|
423
|
+
|
424
|
+
othHeaders.each do |header|
|
425
|
+
out.addColumn(header, other.getColumn(header))
|
426
|
+
end
|
427
|
+
|
428
|
+
return out
|
429
|
+
end
|
430
|
+
|
431
|
+
def addColumn(header, column)
|
432
|
+
pushColumn(header, column)
|
433
|
+
end
|
434
|
+
def <<(row)
|
435
|
+
addRow(row)
|
436
|
+
end
|
437
|
+
def addRow(row)
|
438
|
+
if(row.class != Array)
|
439
|
+
row = [row]
|
440
|
+
end
|
441
|
+
row.size.times do |i|
|
442
|
+
if(row[i] == nil)
|
443
|
+
row[i] = ''
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
headerSize = getHeaders.size
|
448
|
+
rowSize = row.size
|
449
|
+
if(headerSize > rowSize)
|
450
|
+
(headerSize - rowSize).times do |i|
|
451
|
+
row << ''
|
452
|
+
end
|
453
|
+
elsif(rowSize > headerSize)
|
454
|
+
raise("row size error. headerSize:#{headerSize} rowSize:#{rowSize}")
|
455
|
+
end
|
456
|
+
@mx << row.dup
|
457
|
+
end
|
458
|
+
def [](i)
|
459
|
+
return @mx[i]
|
460
|
+
end
|
461
|
+
def []=(key, value)
|
462
|
+
@mx[key] = value
|
463
|
+
end
|
464
|
+
|
465
|
+
def pushColumn(header, column)
|
466
|
+
colPos = @headers.length
|
467
|
+
@headers << header
|
468
|
+
registerMatrix
|
469
|
+
column.each_with_index do |cell, i|
|
470
|
+
if(@mx[i] == nil)
|
471
|
+
@mx[i] = []
|
472
|
+
end
|
473
|
+
@mx[i][colPos] = cell
|
474
|
+
end
|
475
|
+
end
|
476
|
+
#使い勝手が良くないので気をつけて使う(todo参照)
|
477
|
+
def unShiftColumn(header, column)
|
478
|
+
@headers.unshift(header)
|
479
|
+
registerMatrix
|
480
|
+
column.each_with_index do |cell, i|
|
481
|
+
if(@mx[i] == nil)
|
482
|
+
@mx[i] = []
|
483
|
+
end
|
484
|
+
#todo:ヘッダよりでかいrowがある場合バグる。期待していない一番右の値が取れてしまう。
|
485
|
+
@mx[i].unshift(cell)
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
def shiftColumn()
|
490
|
+
header = @headers.shift
|
491
|
+
column = []
|
492
|
+
registerMatrix
|
493
|
+
@mx.each do |row|
|
494
|
+
column << row.shift
|
495
|
+
end
|
496
|
+
return header, column
|
497
|
+
end
|
498
|
+
|
499
|
+
#複数に分割されたテキストファイルを出力する
|
500
|
+
def divide(splitNum)
|
501
|
+
lineNum = (@mx.size / splitNum) + 1
|
502
|
+
mymxs = []
|
503
|
+
tmp = MyMatrix.new
|
504
|
+
tmp.file = @file
|
505
|
+
tmp.addHeaders(getHeaders)
|
506
|
+
@mx.each_with_index do |row, i|
|
507
|
+
tmp << row.dup
|
508
|
+
if((i+1) % lineNum == 0)
|
509
|
+
mymxs << tmp
|
510
|
+
tmp = MyMatrix.new
|
511
|
+
tmp.addHeaders(getHeaders)
|
512
|
+
tmp.file = @file
|
513
|
+
end
|
514
|
+
end
|
515
|
+
mymxs << tmp
|
516
|
+
mymxs.each_with_index do |mymx, i|
|
517
|
+
p i
|
518
|
+
mymx.to_t_with("#{i}")
|
519
|
+
end
|
520
|
+
end
|
521
|
+
#ファイルの中身をSJISにするために使ってる
|
522
|
+
def localEncode(v, enc = 's')
|
523
|
+
case enc
|
524
|
+
when 'u'
|
525
|
+
str = MyMatrix.toutf8(v)
|
526
|
+
when 's'
|
527
|
+
str = MyMatrix.tosjis(v)
|
528
|
+
else
|
529
|
+
str = MyMatrix.tosjis(v)
|
530
|
+
end
|
531
|
+
end
|
532
|
+
#使い方はto_t()を参照。yield。
|
533
|
+
def to_text(outFile)
|
534
|
+
outFile = encodePath(outFile)
|
535
|
+
out = []
|
536
|
+
out << @headers
|
537
|
+
@mx.each do |row|
|
538
|
+
out << row
|
539
|
+
end
|
540
|
+
begin
|
541
|
+
fo = open(outFile, 'wb')
|
542
|
+
rescue => e
|
543
|
+
p "cannot write file...#{outFile}"
|
544
|
+
p e
|
545
|
+
sleep(5)
|
546
|
+
retry
|
547
|
+
end
|
548
|
+
out.each_with_index do |row, i|
|
549
|
+
if(row == nil)
|
550
|
+
warn("line #{i} is nil")
|
551
|
+
fo.print("")
|
552
|
+
else
|
553
|
+
str = yield(row)
|
554
|
+
fo.print(str)
|
555
|
+
end
|
556
|
+
fo.print("\r\n")
|
557
|
+
end
|
558
|
+
fo.close
|
559
|
+
end
|
560
|
+
# テキスト出力する
|
561
|
+
def to_t(outFile=nil, opts={})
|
562
|
+
if(!outFile)
|
563
|
+
outFile = @file
|
564
|
+
end
|
565
|
+
|
566
|
+
#拡張子の判別
|
567
|
+
ext = File.extname(outFile).downcase
|
568
|
+
case ext
|
569
|
+
when '.csv'
|
570
|
+
opts[:separator] ||= ','
|
571
|
+
opts[:escape] ||= true
|
572
|
+
when '.xls'
|
573
|
+
p 'use Tab-Separated-Value text format.'
|
574
|
+
outFile = outFile + '.txt'
|
575
|
+
when '.xlsx'
|
576
|
+
p 'use Tab-Separated-Value text format.'
|
577
|
+
outFile = outFile + '.txt'
|
578
|
+
else
|
579
|
+
#do nothing
|
580
|
+
end
|
581
|
+
#デフォルトオプションの設定
|
582
|
+
opts[:enc] ||= 's'
|
583
|
+
opts[:escape] ||= false
|
584
|
+
opts[:separator] ||= SEPARATOR
|
585
|
+
|
586
|
+
to_text(outFile) do |row|
|
587
|
+
orow = []
|
588
|
+
if(opts[:escape])
|
589
|
+
row.each do |cell|
|
590
|
+
orow << myescape(cell)
|
591
|
+
end
|
592
|
+
else
|
593
|
+
row.each do |cell|
|
594
|
+
orow << cell.to_s.gsub(/[#{opts[:separator]}\r\n]/, '')
|
595
|
+
end
|
596
|
+
end
|
597
|
+
|
598
|
+
begin
|
599
|
+
str = localEncode(orow.join(opts[:separator]), opts[:enc])
|
600
|
+
rescue Encoding::UndefinedConversionError
|
601
|
+
orow.each do |ele|
|
602
|
+
begin
|
603
|
+
localEncode(ele, opts[:enc])
|
604
|
+
rescue
|
605
|
+
raise "encode error.#{ele}\n(#{orow})"
|
606
|
+
end
|
607
|
+
end
|
608
|
+
|
609
|
+
@log.debug(row.join(opts[:separator]))
|
610
|
+
end
|
611
|
+
str
|
612
|
+
end
|
613
|
+
end
|
614
|
+
def myescape(cell)
|
615
|
+
o = cell.to_s.dup
|
616
|
+
o.gsub!(/"/, '""')
|
617
|
+
if o =~ /[",']/
|
618
|
+
#'
|
619
|
+
o = "\"#{o}\""
|
620
|
+
end
|
621
|
+
return o
|
622
|
+
end
|
623
|
+
# 読み込んだファイル名にpostfixを付与してテキストファイル出力する
|
624
|
+
def to_t_with(postfix="out", opts={})
|
625
|
+
opath = MyMatrix.make_path(@file, {:ext=>nil, :postfix=>postfix})
|
626
|
+
to_t(opath, opts)
|
627
|
+
return opath
|
628
|
+
end
|
629
|
+
|
630
|
+
#CSV出力する。ダブルクオーテーションやカンマをエスケープする。
|
631
|
+
def to_csv(outFile)
|
632
|
+
to_t(outFile, {:separator=>',', :escape=>true})
|
633
|
+
end
|
634
|
+
|
635
|
+
#ヘッダのコピーを返却する
|
636
|
+
def getHeaders
|
637
|
+
out = @headers.dup
|
638
|
+
return out
|
639
|
+
end
|
640
|
+
#ヘッダを置き換える
|
641
|
+
def replaceHeader(before, after)
|
642
|
+
@headers[@headerH[before]] = after
|
643
|
+
registerMatrix
|
644
|
+
end
|
645
|
+
|
646
|
+
# colNameの値がvalueの行のうち先頭のものを返却する。todo:名称がよくない。
|
647
|
+
def index(colName, value)
|
648
|
+
out = nil
|
649
|
+
col = getColumn(colName)
|
650
|
+
col.each_with_index do |cell, i|
|
651
|
+
if(value == cell)
|
652
|
+
out = i
|
653
|
+
break
|
654
|
+
end
|
655
|
+
end
|
656
|
+
return out
|
657
|
+
end
|
658
|
+
|
659
|
+
# colnameの値がvalueの行のもののインデックス値を配列で返却する。todo:名称がよくない。
|
660
|
+
def searchIndexes(colName, value)
|
661
|
+
out = []
|
662
|
+
col = getColumn(colName)
|
663
|
+
col.each_with_index do |cell, i|
|
664
|
+
if(value == cell)
|
665
|
+
out << i
|
666
|
+
end
|
667
|
+
end
|
668
|
+
return out
|
669
|
+
end
|
670
|
+
|
671
|
+
# colnameの値がvalueの行のrowを配列で返却する。todo:名称がよくない。
|
672
|
+
def search(colName, value)
|
673
|
+
indexes = []
|
674
|
+
col = getColumn(colName)
|
675
|
+
col.each_with_index do |cell, i|
|
676
|
+
if(value == cell)
|
677
|
+
indexes << i
|
678
|
+
end
|
679
|
+
end
|
680
|
+
out = self.empty
|
681
|
+
indexes.each do |index|
|
682
|
+
out << @mx[index]
|
683
|
+
end
|
684
|
+
return out
|
685
|
+
end
|
686
|
+
# ヘッダを追加する(配列)
|
687
|
+
def addHeaders(aheaders)
|
688
|
+
@headers.concat(aheaders).uniq!
|
689
|
+
|
690
|
+
registerMatrix
|
691
|
+
end
|
692
|
+
|
693
|
+
# ヘッダを追加する
|
694
|
+
def addHeader(key)
|
695
|
+
addHeaders([key])
|
696
|
+
end
|
697
|
+
|
698
|
+
#行数を返却する
|
699
|
+
def size
|
700
|
+
return @mx.size
|
701
|
+
end
|
702
|
+
|
703
|
+
#未検証。「要素の重複判定は、Object#eql? により行われます。」http://www.ruby-lang.org/ja/old-man/html/Array.html#uniq
|
704
|
+
def uniq!
|
705
|
+
@mx.uniq!
|
706
|
+
end
|
707
|
+
|
708
|
+
def shift
|
709
|
+
return @mx.shift
|
710
|
+
end
|
711
|
+
def unshift(var)
|
712
|
+
return @mx.unshift(var)
|
713
|
+
end
|
714
|
+
def pop
|
715
|
+
return @mx.pop
|
716
|
+
end
|
717
|
+
def push(var)
|
718
|
+
return @mx.push(var)
|
719
|
+
end
|
720
|
+
def delete_at(pos)
|
721
|
+
@mx.delete_at(pos)
|
722
|
+
end
|
723
|
+
|
724
|
+
#未検証。「要素を順番にブロックに渡して評価し、その結果が真になった要素を すべて削除します。」
|
725
|
+
def delete_if
|
726
|
+
out = @mx.delete_if do |row|
|
727
|
+
yield(row)
|
728
|
+
end
|
729
|
+
@mx = out
|
730
|
+
end
|
731
|
+
def delete(v)
|
732
|
+
@mx.delete(v)
|
733
|
+
end
|
734
|
+
#ブロックがTrueになる、配列(参照)を返却するメソッド
|
735
|
+
def find
|
736
|
+
#todo rowsを返却するのと、Mymatrxixを返却するのとどっちがイイのか。。
|
737
|
+
rows = []
|
738
|
+
@mx.each do |row|
|
739
|
+
if(yield(row))
|
740
|
+
rows << row.dup
|
741
|
+
end
|
742
|
+
end
|
743
|
+
return rows
|
744
|
+
end
|
745
|
+
|
746
|
+
#headersに記載の
|
747
|
+
def select(headers)
|
748
|
+
out = self.class.new
|
749
|
+
headers.each do |header|
|
750
|
+
out.addColumn(header, getColumn(header))
|
751
|
+
end
|
752
|
+
out.file = @file
|
753
|
+
return out
|
754
|
+
end
|
755
|
+
|
756
|
+
#fromColName => toColNameのハッシュを作成する。
|
757
|
+
#fromColNameの値が同じだとtoColNameが上書きされるので使いにくいと思われる。
|
758
|
+
def makeHash(fromColName, toColName)
|
759
|
+
out = Hash.new
|
760
|
+
@mx.each do |row|
|
761
|
+
from = getValue(row, fromColName)
|
762
|
+
to = getValue(row, toColName)
|
763
|
+
out[from] = to
|
764
|
+
end
|
765
|
+
return out
|
766
|
+
end
|
767
|
+
|
768
|
+
#colnameがキーのハッシュを作る。valueはrowの配列。
|
769
|
+
def makeKey(colname)
|
770
|
+
out = {}
|
771
|
+
self.each do |row|
|
772
|
+
key = self.val(row, colname)
|
773
|
+
if(out[key] == nil)
|
774
|
+
out[key] = []
|
775
|
+
end
|
776
|
+
out[key] << row
|
777
|
+
end
|
778
|
+
return out
|
779
|
+
end
|
780
|
+
|
781
|
+
#MyipcMatrixとの互換性のため。getValueのエイリアス
|
782
|
+
def getCrrValue(row, str)
|
783
|
+
p 'this class is not MyipcMatrix.'
|
784
|
+
getValue(row, str)
|
785
|
+
end
|
786
|
+
|
787
|
+
def concatCells(headers, colname)
|
788
|
+
addHeaders([colname])
|
789
|
+
@mx.each do |row|
|
790
|
+
val = []
|
791
|
+
headers.each do |header|
|
792
|
+
val << getValue(row, header)
|
793
|
+
end
|
794
|
+
setValue(row, colname, val.join('_').gsub(/_+/, '_'))
|
795
|
+
end
|
796
|
+
end
|
797
|
+
|
798
|
+
#読み込んだファイルのパスを返却する
|
799
|
+
def getPath
|
800
|
+
return @file
|
801
|
+
end
|
802
|
+
#ファイルパスを設定する。 to_tを引数なしで使うと、設定したパスにファイルが生成される。
|
803
|
+
def setPath(path)
|
804
|
+
@file = path
|
805
|
+
end
|
806
|
+
|
807
|
+
# strを含む(/#{str}/)ヘッダ名を配列で返却する。
|
808
|
+
def searchHeader(str)
|
809
|
+
out = []
|
810
|
+
getHeaders.each do |header|
|
811
|
+
if(header =~ /#{str}/)
|
812
|
+
out << header
|
813
|
+
end
|
814
|
+
end
|
815
|
+
end
|
816
|
+
|
817
|
+
#n分割した配列を返却する
|
818
|
+
def devide(n)
|
819
|
+
out = []
|
820
|
+
mx = @mx.dup
|
821
|
+
eleSize = mx.size/n
|
822
|
+
n.times do |i|
|
823
|
+
o = self.empty
|
824
|
+
eleSize.times do |j|
|
825
|
+
o << mx.shift
|
826
|
+
end
|
827
|
+
out << o
|
828
|
+
end
|
829
|
+
#@mx.size%n分余ってるので、追加
|
830
|
+
mx.each do |ele|
|
831
|
+
out[n-1] << ele
|
832
|
+
end
|
833
|
+
return out
|
834
|
+
end
|
835
|
+
#compareHeaderの値の中に、valuesに書かれた値があったら、targetHeaderにフラグを立てる
|
836
|
+
def addFlg(targetHeader, compareHeader, values, flgValue='1')
|
837
|
+
compares = getColumn(compareHeader)
|
838
|
+
values.each do|value|
|
839
|
+
i = compares.index(value)
|
840
|
+
if(i)
|
841
|
+
setValue(@mx[i], targetHeader, flgValue)
|
842
|
+
else
|
843
|
+
#raise "VALUE NOT FOUND:#{value}"
|
844
|
+
end
|
845
|
+
end
|
846
|
+
end
|
847
|
+
|
848
|
+
def without(regexp_or_string)
|
849
|
+
if(regexp_or_string.class == String)
|
850
|
+
regexp = /#{regexp_or_string}/
|
851
|
+
else
|
852
|
+
regexp = regexp_or_string
|
853
|
+
end
|
854
|
+
newHeaders = []
|
855
|
+
@headers.each do |header|
|
856
|
+
if(header =~ regexp)
|
857
|
+
else
|
858
|
+
newHeaders << header
|
859
|
+
end
|
860
|
+
end
|
861
|
+
out = select(newHeaders)
|
862
|
+
return out
|
863
|
+
end
|
864
|
+
|
865
|
+
#行が空(ヘッダはそのまま)のコピーを返却する
|
866
|
+
def empty
|
867
|
+
out = self.dup
|
868
|
+
out.empty!
|
869
|
+
return out
|
870
|
+
end
|
871
|
+
|
872
|
+
#selfの行を空にする
|
873
|
+
def empty!
|
874
|
+
@mx = []
|
875
|
+
return self
|
876
|
+
end
|
877
|
+
def fill(rows)
|
878
|
+
rows.each do |row|
|
879
|
+
self << row
|
880
|
+
end
|
881
|
+
return self
|
882
|
+
end
|
883
|
+
|
884
|
+
#行番号を付与する
|
885
|
+
def with_serial(headerName = 'No.')
|
886
|
+
out = self.empty
|
887
|
+
out.addHeaders([headerName], 1)
|
888
|
+
self.each_with_index do |row, i|
|
889
|
+
no = i + 1
|
890
|
+
newRow = [no].concat(row)
|
891
|
+
out << newRow
|
892
|
+
end
|
893
|
+
return out
|
894
|
+
end
|
895
|
+
|
896
|
+
|
897
|
+
def count(header, value)
|
898
|
+
out = 0
|
899
|
+
arr = getColumn(header)
|
900
|
+
arr.each do |ele|
|
901
|
+
if(ele =~ /#{value}/)
|
902
|
+
out += 1
|
903
|
+
end
|
904
|
+
end
|
905
|
+
return out
|
906
|
+
end
|
907
|
+
#全件カウントして、[value, count] という配列に格納する
|
908
|
+
def countup(header)
|
909
|
+
out = []
|
910
|
+
values = getColumn(header).uniq
|
911
|
+
values.each do |value|
|
912
|
+
out << [value, self.count(header, value)]
|
913
|
+
end
|
914
|
+
return out
|
915
|
+
end
|
916
|
+
def getDoubles(arr)
|
917
|
+
doubles = arr.select do |e|
|
918
|
+
arr.index(e) != arr.rindex(e)
|
919
|
+
end
|
920
|
+
doubles.uniq!
|
921
|
+
return doubles
|
922
|
+
end
|
923
|
+
|
924
|
+
def filter(header, value)
|
925
|
+
out = empty
|
926
|
+
@mx.each do|row|
|
927
|
+
v = getValue(row, header)
|
928
|
+
if(v == value)
|
929
|
+
out << row
|
930
|
+
end
|
931
|
+
end
|
932
|
+
return out
|
933
|
+
end
|
934
|
+
#配列と引き算とかする際に使われる。
|
935
|
+
def to_ary
|
936
|
+
arr = []
|
937
|
+
@mx.each do |row|
|
938
|
+
#arr << row.dup
|
939
|
+
arr << row
|
940
|
+
end
|
941
|
+
return arr
|
942
|
+
end
|
943
|
+
def to_s
|
944
|
+
out = ''
|
945
|
+
@mx.each do |row|
|
946
|
+
out = out + row.to_s + "\n"
|
947
|
+
end
|
948
|
+
return out
|
949
|
+
end
|
950
|
+
def to_s_with_header
|
951
|
+
out = self.getHeaders.to_s + "\n"
|
952
|
+
out = out + self.to_s
|
953
|
+
end
|
954
|
+
def concat(mx, opt={})
|
955
|
+
notfoundHeaders = []
|
956
|
+
mx.each do |row|
|
957
|
+
o = []
|
958
|
+
mx.getHeaders.each do |head|
|
959
|
+
begin
|
960
|
+
self.setValue(o, head, mx.getValue(row, head))
|
961
|
+
rescue => e
|
962
|
+
#p e
|
963
|
+
if(opt[:loose]==true)
|
964
|
+
self.addHeaders([head])
|
965
|
+
#p "#{head} added"
|
966
|
+
retry
|
967
|
+
else
|
968
|
+
notfoundHeaders << head
|
969
|
+
end
|
970
|
+
end
|
971
|
+
end
|
972
|
+
self << o
|
973
|
+
end
|
974
|
+
if(notfoundHeaders.size > 0)
|
975
|
+
raise "notfoundHeader : #{notfoundHeaders.uniq.join(',')}"
|
976
|
+
end
|
977
|
+
return self
|
978
|
+
end
|
979
|
+
def concatFile(file, opt={})
|
980
|
+
#p file
|
981
|
+
mx = MyMatrix.new(file)
|
982
|
+
self.concat(mx, opt)
|
983
|
+
return self
|
984
|
+
end
|
985
|
+
#フォルダ内ファイルの結合。絶対パスを指定する
|
986
|
+
def concatDir(dir)
|
987
|
+
dir = File.expand_path(dir)
|
988
|
+
Dir.entries(dir).each do |ent|
|
989
|
+
if(ent =~ /^\./)
|
990
|
+
else
|
991
|
+
#p ent
|
992
|
+
|
993
|
+
file = dir + '/' + ent
|
994
|
+
#p "concat:#{file}"
|
995
|
+
nmx = MyMatrix.new(file)
|
996
|
+
self.concat(nmx)
|
997
|
+
end
|
998
|
+
end
|
999
|
+
|
1000
|
+
end
|
1001
|
+
=begin
|
1002
|
+
def concat!(mx)
|
1003
|
+
o = self.concat(mx)
|
1004
|
+
self = o
|
1005
|
+
return self
|
1006
|
+
end
|
1007
|
+
def concatFile!(file)
|
1008
|
+
o = self.concatFile(file)
|
1009
|
+
self = o
|
1010
|
+
return self
|
1011
|
+
end
|
1012
|
+
=end
|
1013
|
+
def flushCol(colname)
|
1014
|
+
@mx.each do |row|
|
1015
|
+
self.setValue(row, colname, '')
|
1016
|
+
end
|
1017
|
+
return self
|
1018
|
+
end
|
1019
|
+
def sortBy(colname, reverse=false)
|
1020
|
+
sortmx = []
|
1021
|
+
self.each do |row|
|
1022
|
+
key = self.getValue(row, colname)
|
1023
|
+
sortmx << [key, row]
|
1024
|
+
end
|
1025
|
+
sortmx.sort!
|
1026
|
+
self.empty!
|
1027
|
+
sortmx.each do |keyrow|
|
1028
|
+
self << keyrow[1]
|
1029
|
+
end
|
1030
|
+
return self
|
1031
|
+
end
|
1032
|
+
def dupRow(row, destmx, destrow, headers)
|
1033
|
+
headers.each do |head|
|
1034
|
+
val = self.getValue(row, head)
|
1035
|
+
destmx.setValue(destrow, head, val)
|
1036
|
+
end
|
1037
|
+
return destrow
|
1038
|
+
end
|
1039
|
+
def setSame(head, headValue, hash)
|
1040
|
+
idxs = self.searchIndexes(head, headValue)
|
1041
|
+
idxs.each do |idx|
|
1042
|
+
hash.each_pair do |key, value|
|
1043
|
+
self.setValue(@mx[idx], key, value)
|
1044
|
+
end
|
1045
|
+
end
|
1046
|
+
end
|
1047
|
+
|
1048
|
+
#都道府県市区町村コードの桁そろえ
|
1049
|
+
#Excelで先頭の0が落ちて桁が変わるため
|
1050
|
+
def correctCityCodes!(colname = '都道府県市区町村コード')
|
1051
|
+
self.each do |row|
|
1052
|
+
code = self.val(row, colname)
|
1053
|
+
if(code.length == 4)
|
1054
|
+
self.setValue(row, colname, sprintf("%05d", code))
|
1055
|
+
elsif(code.length == 5)
|
1056
|
+
#correct
|
1057
|
+
else
|
1058
|
+
raise "Citycode length error. '#{code}'"
|
1059
|
+
end
|
1060
|
+
end
|
1061
|
+
return self
|
1062
|
+
end
|
1063
|
+
|
1064
|
+
#末尾空白の削除
|
1065
|
+
def delEndSp!
|
1066
|
+
self.each do |row|
|
1067
|
+
self.getHeaders.each do |head|
|
1068
|
+
val = self.val(row, head)
|
1069
|
+
if(val =~ /(.*)[ ]$/)
|
1070
|
+
self.setValue(row, head, $1)
|
1071
|
+
end
|
1072
|
+
end
|
1073
|
+
end
|
1074
|
+
return self
|
1075
|
+
end
|
1076
|
+
#半角カタカナの全角化
|
1077
|
+
def twoByteKana!
|
1078
|
+
self.each do |row|
|
1079
|
+
self.getHeaders.each do |head|
|
1080
|
+
val = self.val(row, head)
|
1081
|
+
#if(val =~ /[-~]/)
|
1082
|
+
if(val =~ /[-]/)
|
1083
|
+
#p "#{self.file} #{val}"
|
1084
|
+
next
|
1085
|
+
end
|
1086
|
+
#nval = Kconv.kconv(val, Kconv::UTF8, Kconv::UTF8)
|
1087
|
+
#nval = NKF.nkf('-W -w -x --cp932', val)
|
1088
|
+
|
1089
|
+
nval = NKF.nkf('-W -w', val)
|
1090
|
+
|
1091
|
+
if(val!=nval)
|
1092
|
+
#p "#{val}=>#{nval}"
|
1093
|
+
end
|
1094
|
+
self.setValue(row, head, nval)
|
1095
|
+
end
|
1096
|
+
end
|
1097
|
+
return self
|
1098
|
+
end
|
1099
|
+
def self.cp932ize(str)
|
1100
|
+
out = str.dup
|
1101
|
+
cases = [
|
1102
|
+
#['−', '―'], #MINUS SIGN(U+2212) to FULLWIDTH HYPHEN-MINUS(U+2015)(windows)
|
1103
|
+
#↑仕様としては上記が正しいが、運用上MINUS SIGN(U+2212) は FULLWIDTH HYPHEN-MINUS(U+FF0D)に変換する
|
1104
|
+
#キー入力時にMacとWindowsで同じ文字コードとなることが望ましいため。
|
1105
|
+
|
1106
|
+
['〜','~'], #WAVE DASH (U+301C) to FULLWIDTH TILDE(U+FF5E)(windows)
|
1107
|
+
['‖','∥'], #DOUBLE VERTICAL LINE (U+2016, "‖") を PARALLEL TO (U+2225, "∥") に
|
1108
|
+
['—', '―'], #EM DASH (U+2014, "—") を HORIZONTAL BAR (U+2015, "―") に
|
1109
|
+
#以下、キー入力を想定した変換。
|
1110
|
+
['ー', 'ー'], #MacのハイフンF7(google ime)→Windows(googleime):同じ
|
1111
|
+
['ー', 'ー'], #MacのハイフンF8(google ime)→Windows(googleime):同じ
|
1112
|
+
['−', '-'], #MacのハイフンF9[−](google ime)→Windows[-](googleime):違う。MINUS SIGN(U+2212) to FULLWIDTH HYPHEN-MINUS(U+FF0D)
|
1113
|
+
['-', '-'], #MacのハイフンF10(google ime)→Windows(googleime):同じ
|
1114
|
+
#ユニコード固有文字:ノーブレークスペース
|
1115
|
+
['[\u00A0]', ' '],
|
1116
|
+
#yen
|
1117
|
+
['[\u00A5]', '¥'],
|
1118
|
+
# éとè:eの上に´と`
|
1119
|
+
['[\u00E9]', 'e'],['[\u00E8]', 'e'],
|
1120
|
+
#spaces
|
1121
|
+
['[\u2000]', ' '],['[\u2001]', ' '],['[\u2002]', ' '],['[\u2003]', ' '],['[\u2004]', ' '],['[\u2005]', ' '],['[\u2006]', ' '],['[\u2007]', ' '],['[\u2008]', ' '],['[\u2009]', ' '],['[\u200A]', ' '],['[\u205F]', ' ']
|
1122
|
+
]
|
1123
|
+
cases.each do |c|
|
1124
|
+
out.gsub!(/#{c[0]}/, c[1])
|
1125
|
+
end
|
1126
|
+
return out
|
1127
|
+
end
|
1128
|
+
# def save(file)
|
1129
|
+
# p Marshal.dump(self)
|
1130
|
+
# open(file, 'w') do |fo|
|
1131
|
+
# fo.write(Marshal.dump(self))
|
1132
|
+
# end
|
1133
|
+
# end
|
1134
|
+
|
1135
|
+
=begin
|
1136
|
+
def to_xls(opts)
|
1137
|
+
if(opts[:out] =~ /.xls$/)
|
1138
|
+
else
|
1139
|
+
raise "not outfile"
|
1140
|
+
end
|
1141
|
+
opts[:template] ||= opts[:out]
|
1142
|
+
|
1143
|
+
opts[:offset_r] ||= 0
|
1144
|
+
opts[:offset_c] ||= 0
|
1145
|
+
|
1146
|
+
xl = Spreadsheet.open(encodePath(opts[:template]), 'r')
|
1147
|
+
sheet = xl.worksheet(0)
|
1148
|
+
@headers.each_with_index do |head, i|
|
1149
|
+
ab_row = opts[:offset_r]
|
1150
|
+
ab_col = opts[:offset_c] + i
|
1151
|
+
sheet[ab_row, ab_col] = head
|
1152
|
+
end
|
1153
|
+
self.each_with_index do |row, i|
|
1154
|
+
row.each_with_index do |cell, j|
|
1155
|
+
ab_row = opts[:offset_r] + i + 1
|
1156
|
+
#↑ヘッダ分1オフセット
|
1157
|
+
ab_col = opts[:offset_c] + j
|
1158
|
+
sheet[ab_row, ab_col] = cell
|
1159
|
+
end
|
1160
|
+
end
|
1161
|
+
|
1162
|
+
xl.write(opts[:out])
|
1163
|
+
|
1164
|
+
end
|
1165
|
+
=end
|
1166
|
+
#Arrayっぽく使うためのメソッド。内部の@mx.first
|
1167
|
+
def first
|
1168
|
+
@mx[0]
|
1169
|
+
end
|
1170
|
+
#Arrayっぽく使うためのメソッド。内部の@mx.last
|
1171
|
+
def last
|
1172
|
+
out = @mx[self.size-1]
|
1173
|
+
end
|
1174
|
+
def empty?
|
1175
|
+
@mx.empty?
|
1176
|
+
end
|
1177
|
+
#num文字以上の項目をnum文字に丸める
|
1178
|
+
def cutOff(head, num)
|
1179
|
+
self.each do |row|
|
1180
|
+
v = self.val(row, head)
|
1181
|
+
if(v =~ /(.{#{num}})/)
|
1182
|
+
self.setValue(row, head, $1)
|
1183
|
+
end
|
1184
|
+
end
|
1185
|
+
end
|
1186
|
+
def self.make_path(path, opts={ })
|
1187
|
+
# opath = makepath(@file, {:ext=>nil, :postfix=>postfix})
|
1188
|
+
dir = File.dirname(path)
|
1189
|
+
ext = opts[:ext]
|
1190
|
+
ext ||= File.extname(path)
|
1191
|
+
postfix = opts[:postfix].to_s
|
1192
|
+
|
1193
|
+
basename = File.basename(path, ".*")
|
1194
|
+
opath = (MyMatrix.new.encodePath("#{dir}/#{basename}_#{postfix}#{ext}"))
|
1195
|
+
end
|
1196
|
+
end
|
1197
|
+
|
1198
|
+
#ruby -Ks で利用する場合。ruby1.9では使えないはず。obsolete
|
1199
|
+
class SjisMyMatrix < MyMatrix
|
1200
|
+
def getValue(row, col)
|
1201
|
+
col = MyMatrix.toutf8(col)
|
1202
|
+
MyMatrix.tosjis(super(row, col))
|
1203
|
+
end
|
1204
|
+
def setValue(row, col, value)
|
1205
|
+
col = MyMatrix.toutf8(col)
|
1206
|
+
value = MyMatrix.toutf8(value)
|
1207
|
+
super(row, col, value)
|
1208
|
+
end
|
1209
|
+
def addHeaders(hs)
|
1210
|
+
arr =[]
|
1211
|
+
hs.each do |ele|
|
1212
|
+
arr << MyMatrix.toutf8(ele)
|
1213
|
+
end
|
1214
|
+
super(arr)
|
1215
|
+
end
|
1216
|
+
def getHeaders
|
1217
|
+
out = []
|
1218
|
+
arr = super()
|
1219
|
+
arr.each do |ele|
|
1220
|
+
out << MyMatrix.tosjis(ele)
|
1221
|
+
end
|
1222
|
+
return out
|
1223
|
+
end
|
1224
|
+
end
|
1225
|
+
|
1226
|
+
|
1227
|
+
#rails で使う場合。obsolete
|
1228
|
+
class MyRailsMatrix < MyMatrix
|
1229
|
+
def headers2db(t)
|
1230
|
+
getHeaders.each do |header|
|
1231
|
+
t.column header, :string
|
1232
|
+
end
|
1233
|
+
end
|
1234
|
+
end
|
1235
|
+
|