Class: XlsxKit::Workbook

Inherits:
Object
  • Object
show all
Defined in:
lib/xlsxkit/workbook.rb

Overview

XLSX Workbook 高层 API

用法: wb = XlsxKit::Workbook.open('data.xlsx') wb.sheet_names # => ["Sheet1", "Sheet2"] wb.read_rows('Sheet1') do |row| puts row.inspect # ["A1值", "B1值", ...] end wb.to_json('Sheet1') # => JSON 字符串 wb.to_a('Sheet1') # => [[...], [...], ...] 原生 Ruby 数组

Defined Under Namespace

Classes: RelsHandler, SharedStringsHandler, SheetRowHandler, WorkbookHandler

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path) ⇒ Workbook

Returns a new instance of Workbook.



40
41
42
43
# File 'lib/xlsxkit/workbook.rb', line 40

def initialize(path)
  @path = path
  @shared_strings = nil
end

Instance Attribute Details

#path ⇒ Object (readonly)

Returns the value of attribute path.



38
39
40
# File 'lib/xlsxkit/workbook.rb', line 38

def path
  @path
end

Class Method Details

.open(path) {|wb| ... } ⇒ Object

Yields:

  • (wb)


45
46
47
48
49
# File 'lib/xlsxkit/workbook.rb', line 45

def self.open(path)
  wb = new(path)
  yield wb if block_given?
  wb
end

Instance Method Details

#read_rows(name = 0, headers: false) {|Array<value> 或 Hash| ... } ⇒ Object

流式读取指定 sheet,逐行 yield。

Parameters:

  • name (String, Integer) (defaults to: 0) —

    sheet 名称或序号(0-based)

  • headers (Boolean) (defaults to: false) —

    第一行作为表头(返回 Hash 行)

Yields:

  • (Array<value> 或 Hash) —

    数据行



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
# File 'lib/xlsxkit/workbook.rb', line 63

def read_rows(name = 0, headers: false)
  target = resolve_sheet(name)
  return enum_for(:read_rows, name, headers: headers) unless block_given?

  header_row = nil
  row_handler = SheetRowHandler.new(load_shared_strings)

  # 第一次扫描:解析 xml,逐行回调
  ZipReader.open(@path) do |zip|
    xml = zip.read_entry_utf8(target[:path])
    return unless xml

    io = StringIO.new(xml)
    SAXParser.parse(io, row_handler)
  end

  rows = row_handler.rows
  if headers && !rows.empty?
    header_row = rows.first
    rows[1..].each do |row|
      yield hashify(header_row, row)
    end
  else
    rows.each { |row| yield row }
  end
end

#sheet_names ⇒ Object

返回所有 sheet 名称。



53
54
55
# File 'lib/xlsxkit/workbook.rb', line 53

def sheet_names
  @sheet_names ||= parse_workbook
end

#to_a(name = 0, headers: false) ⇒ Object

读取全部数据到原生 Ruby 二维数组。



92
93
94
95
96
97
98
# File 'lib/xlsxkit/workbook.rb', line 92

def to_a(name = 0, headers: false)
  rows = read_rows(name).to_a
  return rows unless headers && rows.size > 1

  header_row = rows.first
  rows[1..].map { |row| hashify(header_row, row) }
end

#to_csv(name = 0, headers: false) ⇒ Object

读取并转为 CSV 字符串。



120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/xlsxkit/workbook.rb', line 120

def to_csv(name = 0, headers: false)
  out = +''
  first = true
  read_rows(name) do |row|
    if headers && first
      first = false
      next
    end
    out << row.map { |c| csv_escape(c) }.join(',') << "\n"
  end
  out
end

#to_csv_file(path, name = 0, headers: false) ⇒ Object

逐行生成 CSV(流式,适合大数据量直接写文件)。



135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/xlsxkit/workbook.rb', line 135

def to_csv_file(path, name = 0, headers: false)
  File.open(path, 'w:UTF-8') do |f|
    first = true
    read_rows(name) do |row|
      if headers && first
        first = false
        next
      end
      f.puts(row.map { |c| csv_escape(c) }.join(','))
    end
  end
end

#to_json(name = 0, headers: false, pretty: false) ⇒ Object

读取并转为 JSON 字符串。



102
103
104
105
# File 'lib/xlsxkit/workbook.rb', line 102

def to_json(name = 0, headers: false, pretty: false)
  data = to_a(name, headers: headers)
  pretty ? JSON.pretty_generate(data) : JSON.generate(data)
end

#to_json_file(path, name = 0, headers: false, pretty: false) ⇒ Object

读取并写入 JSON 文件。



109
110
111
112
# File 'lib/xlsxkit/workbook.rb', line 109

def to_json_file(path, name = 0, headers: false, pretty: false)
  json = to_json(name, headers: headers, pretty: pretty)
  File.write(path, json)
end