fastsheet 0.0.7 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6965671d803c3232aae8e31b15a5ac5df9c6f109
4
- data.tar.gz: 8545afaf2906b9fa1fa363f2933ec29a6ded458e
3
+ metadata.gz: e6eb7e299b220f69ff05cb1dd1bb015409e4cc31
4
+ data.tar.gz: 972681080beecd7165e47d0e0ddda8305004e7a9
5
5
  SHA512:
6
- metadata.gz: 418f795f3bbbc469060f81a2703fd1f60308ca25643731bb421dc2eaa025156ec562270b39b61287d53193abe34e32a10bf3c09736a52147ec0dffdaa50a9130
7
- data.tar.gz: c5b02accdb8303fb3b7d4be7e74d14e69470f86ac4c0fa04d85dadcc74ea56b88623b194c4fe3d7baf47aa6549398ac83ca758eed9b8d45b7202872156558b33
6
+ metadata.gz: 9155761df20a035bfa2e550600db4f5daa50813dac66b6558604649a1cb22b2d07db828c96ad300c5b7213eb5213a9d7ad0e1946dbc9b709b7a51c10b373beb3
7
+ data.tar.gz: 730e69d383da0b13e1dafc49ea2a9e0c287ad7ea56583e08fe01ebae58f89814cd20c24e32e908ba9638a1021017af02cdaa7c8e4e666f2e0a7b0cb172774380
data/.gitignore CHANGED
@@ -1,13 +1,14 @@
1
- /.bundle/
2
- /.yardoc
3
- /*.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
10
- /target/
11
- /**/*.so
12
- /*.gem
13
- /**/*.log
1
+ Makefile
2
+ .yardoc
3
+ .bundle/
4
+ _yardoc/
5
+ coverage/
6
+ doc/
7
+ pkg/
8
+ spec/reports/
9
+ tmp/
10
+ **/target/
11
+ **/*.so
12
+ **/*.gem
13
+ **/*.log
14
+ **/*.lock
data/README.md CHANGED
@@ -2,33 +2,10 @@
2
2
 
3
3
  Fastest ruby gem for reading Excel documents.
4
4
 
5
- Benchmark:
6
- ```shell
7
- $ bin/benchmark
8
- Benchmark reading row №2991 from `./first_file.xlsx` 15 times...
9
- ┌───────────┬───────────┐
10
- │ Reader │ Real Time │
11
- ├───────────┼───────────┤
12
- │ Roo │ 161.3275 │
13
- ├───────────┼───────────┤
14
- │ Fastsheet │ 4.3765 │
15
- └───────────┴───────────┘
16
- Fastsheet is 37 times faster
17
-
18
- $ bin/benchmark
19
- Benchmark reading row №7146 from `./second_file.xlsx` 15 times...
20
- ┌───────────┬───────────┐
21
- │ Reader │ Real Time │
22
- ├───────────┼───────────┤
23
- │ Roo │ 897.4474 │
24
- ├───────────┼───────────┤
25
- │ Fastsheet │ 19.0869 │
26
- └───────────┴───────────┘
27
- Fastsheet is 47 times faster
28
- ```
29
-
30
5
  ## Installation
31
6
 
7
+ **You should have rust installed to use this gem.**
8
+
32
9
  Add this line to your application's Gemfile:
33
10
 
34
11
  ```ruby
@@ -45,24 +22,38 @@ Or install it yourself as:
45
22
 
46
23
  ## Usage
47
24
 
48
- This lib returns sheet as array of arrays, so you are free to use it however you want:
25
+ Open a sheet:
49
26
 
50
27
  ```ruby
51
28
  require 'fastsheet'
52
29
 
53
- sheet = Xlsx.new('path/to/sheet.xlsx')
30
+ sheet = Fastsheet::Sheet.new('path/to/sheet.xlsx')
54
31
 
55
- # get all rows
56
- sheet.rows
32
+ # number of columns
33
+ sheet.width
34
+
35
+ # number of rows
36
+ sheet.height
57
37
  ```
58
38
 
59
- That's all API for now :smile: . Feel free to [open an issue](http://github.com/dkkoval/fastsheet/issues) if you need more.
39
+ Get rows or columns:
40
+
41
+ ```ruby
42
+ sheet.rows
43
+ sheet.columns
44
+
45
+ sheet.row(42)
46
+ sheet.column(1)
47
+ ```
60
48
 
61
- ## Development
49
+ Iterators (returns enumerator if no block given):
62
50
 
63
- After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
51
+ ```ruby
52
+ sheet.each_row { |r| ... }
53
+ sheet.each_column { |c| ... }
54
+ ```
64
55
 
65
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
56
+ That's all API for now. Feel free to [open an issue](http://github.com/dkkoval/fastsheet/issues) if you need more.
66
57
 
67
58
  ## Contributing
68
59
 
data/Rakefile CHANGED
@@ -1,11 +1,14 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/gem_tasks'
4
- require 'rake/clean'
5
- require 'rake/testtask'
6
1
  require 'bundler/setup'
7
- require 'thermite/tasks'
8
2
 
9
- Thermite::Tasks.new
3
+ desc 'Build native extension'
4
+ task :build do
5
+ ruby 'extconf.rb'
6
+ end
7
+
8
+ # TODO
9
+ desc 'Run tests'
10
+ task :test do
11
+ puts "no tests"
12
+ end
10
13
 
11
- task default: 'thermite:build'
14
+ task default: [:build, :test]
data/bin/.keep ADDED
File without changes
@@ -1,16 +1,13 @@
1
1
  [package]
2
2
  name = "fastsheet"
3
3
  version = "0.1.0"
4
-
5
- [package.metadata.thermite]
6
- github_releases = true
7
- github_release_type = "latest"
4
+ publish = false
5
+ build = "build.rs"
8
6
 
9
7
  [lib]
10
8
  name = "fastsheet"
11
9
  crate-type = ["cdylib"]
12
10
 
13
11
  [dependencies]
14
- ruru = "0.9.3"
15
- lazy_static = "0.2.1"
16
12
  calamine = "0.11.8"
13
+ libc = "0.2"
@@ -0,0 +1,62 @@
1
+ use std::env;
2
+ use std::ffi::OsStr;
3
+ use std::process::Command;
4
+
5
+ fn rbconfig(key: &str) -> Vec<u8> {
6
+ let ruby = match env::var_os("RUBY") {
7
+ Some(val) => val.to_os_string(),
8
+ None => OsStr::new("ruby").to_os_string(),
9
+ };
10
+ let config = Command::new(ruby)
11
+ .arg("-e")
12
+ .arg(format!("print RbConfig::CONFIG['{}']", key))
13
+ .output()
14
+ .unwrap_or_else(|e| panic!("ruby not found: {}", e));
15
+
16
+ config.stdout
17
+ }
18
+
19
+ fn use_static() {
20
+ let ruby_libs = rbconfig("LIBS");
21
+ let libs = String::from_utf8_lossy(&ruby_libs);
22
+
23
+ // Ruby gives back the libs in the form: `-lpthread -lgmp`
24
+ // Cargo wants them as: `-l pthread -l gmp`
25
+ let transformed_lib_args = libs.replace("-l", "-l ");
26
+
27
+ println!("cargo:rustc-link-lib=static=ruby-static");
28
+ println!("cargo:rustc-flags={}", transformed_lib_args);
29
+ }
30
+
31
+ fn use_dylib(lib: Vec<u8>) {
32
+ println!("cargo:rustc-link-lib=dylib={}",
33
+ String::from_utf8_lossy(&lib));
34
+ }
35
+
36
+ fn main() {
37
+ let libdir = rbconfig("libdir");
38
+
39
+ let libruby_static = rbconfig("LIBRUBY_A");
40
+ let libruby_so = rbconfig("RUBY_SO_NAME");
41
+
42
+ match (libruby_static.is_empty(), libruby_so.is_empty()) {
43
+ (false, true) => use_static(),
44
+ (true, false) => use_dylib(libruby_so),
45
+ (false, false) => {
46
+ if env::var_os("RUBY_STATIC").is_some() {
47
+ use_static()
48
+ } else {
49
+ use_dylib(libruby_so)
50
+ }
51
+ },
52
+ _ => {
53
+ let msg = "Error! Could not find LIBRUBY_A or RUBY_SO_NAME. \
54
+ This means that no static, or dynamic libruby was found. \
55
+ Possible solution: build a new Ruby with the `--enable-shared` configure opt.";
56
+ panic!(msg)
57
+ }
58
+ }
59
+
60
+ println!("cargo:rustc-link-search={}",
61
+ String::from_utf8_lossy(&libdir));
62
+ }
@@ -0,0 +1,152 @@
1
+ extern crate libc;
2
+ extern crate calamine;
3
+
4
+ use std::ffi::{CString, CStr};
5
+ use libc::{c_int, c_void, c_char, c_double, uintptr_t};
6
+
7
+ use calamine::{Sheets, DataType};
8
+
9
+ //
10
+ // Prepare Ruby bindings
11
+ //
12
+
13
+ // VALUE (pointer to a ruby object)
14
+ type Value = uintptr_t;
15
+
16
+ // Some ruby constant values
17
+ const NIL: usize = 0x08;
18
+ const TRUE: usize = 0x14;
19
+ const FALSE: usize = 0x00;
20
+
21
+ // Load some Ruby API functions
22
+ extern "C" {
23
+ // Object class
24
+ static rb_cObject: Value;
25
+
26
+ // Modules and classes
27
+ fn rb_define_module(name: *const c_char) -> Value;
28
+ fn rb_define_class_under(outer: Value, name: *const c_char, superclass: Value) -> Value;
29
+ fn rb_define_method(class: Value, name: *const c_char, method: *const c_void, argc: c_int) -> Value;
30
+
31
+ // Set instance variables
32
+ fn rb_iv_set(object: Value, name: *const c_char, value: Value) -> Value;
33
+
34
+ // Array
35
+ fn rb_ary_new() -> Value;
36
+ fn rb_ary_push(array: Value, elem: Value) -> Value;
37
+
38
+ // C data to Ruby
39
+ fn rb_int2big(num: c_int) -> Value;
40
+ fn rb_float_new(num: c_double) -> Value;
41
+ fn rb_utf8_str_new_cstr(str: *const c_char) -> Value;
42
+
43
+ // Ruby string to C string
44
+ fn rb_string_value_cstr(str: *const Value) -> *const c_char;
45
+ }
46
+
47
+ //
48
+ // Utils
49
+ //
50
+
51
+ // C string from Rust string
52
+ pub fn cstr(string: &str) -> CString {
53
+ CString::new(string).unwrap()
54
+ }
55
+
56
+ // Rust string from Ruby string
57
+ pub fn rstr(string: Value) -> String {
58
+ unsafe {
59
+ let s = rb_string_value_cstr(&string);
60
+ CStr::from_ptr(s).to_string_lossy().into_owned()
61
+ }
62
+ }
63
+
64
+ //
65
+ // Functions to use in Ruby
66
+ //
67
+
68
+ // Read the sheet
69
+ unsafe fn read(this: Value, rb_file_name: Value) -> Value {
70
+ let mut document =
71
+ Sheets::open(rstr(rb_file_name))
72
+ .expect("Cannot open file!");
73
+
74
+ // Open first worksheet by default
75
+ //
76
+ // TODO: allow use different worksheets
77
+ let sheet = document.worksheet_range_by_index(0).unwrap();
78
+
79
+ let rows = rb_ary_new();
80
+
81
+ for row in sheet.rows() {
82
+ let new_row = rb_ary_new();
83
+
84
+ for (_, c) in row.iter().enumerate() {
85
+ rb_ary_push(
86
+ new_row,
87
+ match *c {
88
+ // vba error
89
+ DataType::Error(_) => NIL,
90
+ DataType::Empty => NIL,
91
+ DataType::Float(ref f) => rb_float_new(*f as c_double),
92
+ DataType::Int(ref i) => rb_int2big(*i as c_int),
93
+ DataType::Bool(ref b) => if *b { TRUE } else { FALSE },
94
+ DataType::String(ref s) => {
95
+ let st = s.trim();
96
+ if st.is_empty() {
97
+ NIL
98
+ } else {
99
+ rb_utf8_str_new_cstr(cstr(st).as_ptr())
100
+ }
101
+ }
102
+ }
103
+ );
104
+ }
105
+
106
+ rb_ary_push(rows, new_row);
107
+ }
108
+
109
+
110
+ // Set instance variables
111
+ rb_iv_set(
112
+ this,
113
+ cstr("@width").as_ptr(),
114
+ rb_int2big(sheet.width() as i32)
115
+ );
116
+
117
+ rb_iv_set(
118
+ this,
119
+ cstr("@height").as_ptr(),
120
+ rb_int2big(sheet.height() as i32)
121
+ );
122
+
123
+ rb_iv_set(
124
+ this,
125
+ cstr("@rows").as_ptr(),
126
+ rows
127
+ );
128
+
129
+ this
130
+ }
131
+
132
+ // Init_libfastsheet symbol is an entrypoint for the lib
133
+ //
134
+ // This function will be executed when we require the lib.
135
+ //
136
+ #[no_mangle]
137
+ #[allow(non_snake_case)]
138
+ pub unsafe extern fn Init_libfastsheet() {
139
+ let Fastsheet =
140
+ rb_define_module(cstr("Fastsheet").as_ptr());
141
+
142
+ let Sheet =
143
+ rb_define_class_under(Fastsheet, cstr("Sheet").as_ptr(), rb_cObject);
144
+
145
+ rb_define_method(
146
+ Sheet,
147
+ cstr("read!").as_ptr(),
148
+ // Rust function as pointer to C function
149
+ read as *const c_void,
150
+ 1 as c_int
151
+ );
152
+ }
data/extconf.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'mkmf'
2
+ require 'rake'
3
+
4
+ abort unless have_library 'ruby'
5
+ abort unless have_header 'ruby.h'
6
+
7
+ abort unless find_executable 'rustc'
8
+ abort unless cargo = find_executable(ENV.fetch('CARGO', 'cargo'))
9
+
10
+ target_file = 'libfastsheet.so'
11
+
12
+ target = File.join(__dir__, 'ext/fastsheet/target/release', target_file)
13
+ lib_dest = File.join(__dir__, 'lib/fastsheet', target_file)
14
+
15
+ # HACK: rubygems requires Makefile with tasks above
16
+ File.write 'Makefile', <<EOF
17
+ all:
18
+ install:
19
+ clean:
20
+ EOF
21
+ $makefile_created = true
22
+
23
+ Dir.chdir 'ext/fastsheet' do
24
+ when_writing 'Building fastsheet...' do
25
+ sh cargo, 'build', '--release'
26
+ cp target, lib_dest
27
+ end
28
+ end
data/fastsheet.gemspec CHANGED
@@ -20,13 +20,8 @@ Gem::Specification.new do |spec|
20
20
  end
21
21
  spec.bindir = 'bin'
22
22
  spec.require_paths = ['lib']
23
- spec.extensions << 'Rakefile'
23
+ spec.extensions = %w[extconf.rb]
24
24
 
25
- spec.add_runtime_dependency 'thermite', '~> 0.12.1'
26
-
27
- spec.add_development_dependency 'pry', '~> 0.10.4'
28
-
29
- # for pretty benchmark
30
- spec.add_development_dependency 'tty-spinner', '~> 0.7.0'
31
- spec.add_development_dependency 'tty-table', '~> 0.8.0'
25
+ spec.add_development_dependency 'rake', '~>12.0.0'
26
+ spec.add_development_dependency 'pry', '~>0.10.4'
32
27
  end
data/lib/fastsheet.rb CHANGED
@@ -1,5 +1,2 @@
1
- require 'fastsheet/xlsx'
2
- require 'libfastsheet'
3
-
4
- module Fastsheet
5
- end
1
+ require 'fastsheet/libfastsheet'
2
+ require 'fastsheet/sheet'
@@ -0,0 +1,44 @@
1
+ module Fastsheet
2
+ class Sheet
3
+ attr_reader :file_name,
4
+ :rows, :header,
5
+ :width, :height
6
+
7
+ def initialize(file_name, options = {})
8
+ # this method sets @rows, @height and @width
9
+ read!(file_name)
10
+
11
+ @header = @rows.shift if options[:header]
12
+ end
13
+
14
+ def row(n)
15
+ @rows[n]
16
+ end
17
+
18
+ def each_row
19
+ if block_given?
20
+ @rows.each { |r| yield r }
21
+ else
22
+ @rows.each
23
+ end
24
+ end
25
+
26
+ def column(n)
27
+ @rows.map { |r| r[n] }
28
+ end
29
+
30
+ def columns
31
+ (0...@width).inject([]) do |cols, i|
32
+ cols.push column(i)
33
+ end
34
+ end
35
+
36
+ def each_column
37
+ if block_given?
38
+ columns.each { |c| yield c }
39
+ else
40
+ columns.each
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,3 +1,3 @@
1
1
  module Fastsheet
2
- VERSION = '0.0.7'
2
+ VERSION = '0.1.0'
3
3
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastsheet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Koval
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-12 00:00:00.000000000 Z
11
+ date: 2017-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: thermite
14
+ name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.12.1
20
- type: :runtime
19
+ version: 12.0.0
20
+ type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.12.1
26
+ version: 12.0.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: pry
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,56 +38,28 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 0.10.4
41
- - !ruby/object:Gem::Dependency
42
- name: tty-spinner
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: 0.7.0
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: 0.7.0
55
- - !ruby/object:Gem::Dependency
56
- name: tty-table
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: 0.8.0
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: 0.8.0
69
41
  description: Fastest ruby gem for reading Excel documents.
70
42
  email:
71
43
  - dkoval@heliostech.fr
72
44
  executables: []
73
45
  extensions:
74
- - Rakefile
46
+ - extconf.rb
75
47
  extra_rdoc_files: []
76
48
  files:
77
49
  - ".gitignore"
78
- - Cargo.toml
79
50
  - Gemfile
80
- - Gemfile.lock
81
51
  - LICENSE.txt
82
52
  - README.md
83
53
  - Rakefile
84
- - bin/benchmark
85
- - bin/console
54
+ - bin/.keep
55
+ - ext/fastsheet/Cargo.toml
56
+ - ext/fastsheet/build.rs
57
+ - ext/fastsheet/src/lib.rs
58
+ - extconf.rb
86
59
  - fastsheet.gemspec
87
60
  - lib/fastsheet.rb
61
+ - lib/fastsheet/sheet.rb
88
62
  - lib/fastsheet/version.rb
89
- - lib/fastsheet/xlsx.rb
90
- - src/lib.rs
91
63
  homepage: https://github.com/dkkoval/fastsheet
92
64
  licenses:
93
65
  - MIT
@@ -108,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
80
  version: '0'
109
81
  requirements: []
110
82
  rubyforge_project:
111
- rubygems_version: 2.5.2
83
+ rubygems_version: 2.6.11
112
84
  signing_key:
113
85
  specification_version: 4
114
86
  summary: Fast XLSX reader
data/bin/benchmark DELETED
@@ -1,59 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- lib = File.expand_path('../../lib', __FILE__)
4
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
-
6
- require 'benchmark'
7
- require 'tty-spinner'
8
- require 'tty-table'
9
-
10
- require 'fastsheet'
11
- require 'roo'
12
-
13
- FILE = './second_file.xlsx'.freeze
14
- ROW = rand 9000
15
- N = 15
16
-
17
- options = {
18
- hide_cursor: true,
19
- format: :dots,
20
- interval: 20,
21
- clear: true
22
- }
23
-
24
- puts "Benchmark reading row №#{ROW} from `#{FILE}` #{N} times..."
25
-
26
- roo_time = Benchmark.measure('Roo') do
27
- spinner = TTY::Spinner.new('[:spinner] :progress', options)
28
- spinner.auto_spin
29
- N.times do |i|
30
- spinner.update(progress: "Roo: #{i + 1}/#{N} sheets opened ...")
31
- Roo::Excelx.new(FILE).sheet(0).row(ROW)
32
- end
33
- spinner.stop
34
- end
35
-
36
- fastsheet_time = Benchmark.measure('Fastsheet') do
37
- spinner = TTY::Spinner.new('[:spinner] :progress', options)
38
- spinner.auto_spin
39
- N.times do |i|
40
- spinner.update(progress: "Fastsheet: #{i + 1}/#{N} sheets opened ...")
41
- Xlsx.new(FILE).rows[ROW]
42
- end
43
- spinner.stop
44
- end
45
-
46
- table = TTY::Table.new(header: ['Reader', 'Real Time'])
47
-
48
- table << ['Roo', roo_time.real.round(4)]
49
- table << ['Fastsheet', fastsheet_time.real.round(4)]
50
-
51
- renderer = TTY::Table::Renderer::Unicode.new(table)
52
-
53
- renderer.alignments = %i[center center]
54
- renderer.padding = [0, 1, 0, 1]
55
- renderer.border.separator = :each_row
56
-
57
- puts renderer.render
58
-
59
- puts "Fastsheet is #{(roo_time.real / fastsheet_time.real).round} times faster"
data/bin/console DELETED
@@ -1,9 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- lib = File.expand_path('../../lib', __FILE__)
4
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
-
6
- require 'fastsheet'
7
-
8
- require 'pry'
9
- Pry.start
@@ -1,4 +0,0 @@
1
- module Fastsheet
2
- class Xlsx
3
- end
4
- end
data/src/lib.rs DELETED
@@ -1,74 +0,0 @@
1
- #[macro_use] extern crate ruru;
2
- #[macro_use] extern crate lazy_static;
3
-
4
- extern crate calamine;
5
-
6
- use ruru::{Array, Class, RString, Float, Fixnum, Boolean, Object, AnyObject, NilClass};
7
-
8
- use calamine::{Sheets, DataType};
9
-
10
- pub struct Reader {
11
- file: String,
12
- rows: Array
13
- }
14
-
15
- impl Reader {
16
- fn new(file: String) -> Self {
17
- let mut this = Reader {
18
- file: file,
19
- rows: Array::new()
20
- };
21
-
22
- let sheet = Sheets::open(&this.file).unwrap().worksheet_range_by_index(0).unwrap();
23
-
24
- for row in sheet.rows() {
25
- let mut new_row = Array::with_capacity(sheet.width());
26
-
27
- for (_, c) in row.iter().enumerate() {
28
- match *c {
29
- DataType::Error(_) => new_row.push(NilClass::new()),
30
- DataType::String(ref s) => new_row.push(RString::new(s)),
31
- DataType::Empty => new_row.push(NilClass::new()),
32
- DataType::Float(ref f) => new_row.push(Float::new(*f)),
33
- DataType::Int(ref i) => new_row.push(Fixnum::new(*i)),
34
- DataType::Bool(ref b) => new_row.push(Boolean::new(*b))
35
- };
36
- }
37
-
38
- this.rows.push(new_row);
39
- }
40
- this
41
- }
42
-
43
- fn get_rows(&self) -> AnyObject {
44
- self.rows.to_any_object()
45
- }
46
- }
47
-
48
- wrappable_struct!(Reader, ReaderWrapper, READER_WRAPPER);
49
-
50
- class!(Xlsx);
51
-
52
- methods!(
53
- Xlsx,
54
- itself,
55
-
56
- fn ruby_xlsx_new(file: RString) -> AnyObject {
57
- let xlsx_reader = Reader::new(file.unwrap().to_string());
58
-
59
- Class::from_existing("Xlsx").wrap_data(xlsx_reader, &*READER_WRAPPER)
60
- }
61
-
62
- fn ruby_xlsx_rows() -> AnyObject {
63
- itself.get_data(&*READER_WRAPPER).get_rows()
64
- }
65
- );
66
-
67
- #[no_mangle]
68
- #[allow(non_snake_case)]
69
- pub extern fn Init_libfastsheet() {
70
- Class::new("Xlsx", None).define(|itself| {
71
- itself.def_self("new", ruby_xlsx_new);
72
- itself.def("rows", ruby_xlsx_rows)
73
- });
74
- }