rods 0.8.0 → 0.8.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/README +61 -49
- data/Rakefile +1 -1
- data/lib/rods.rb +101 -11
- data/rods.gemspec +2 -3
- metadata +5 -5
data/README
CHANGED
@@ -16,6 +16,8 @@
|
|
16
16
|
Licensed under the same terms as Ruby. No warranty is provided.
|
17
17
|
|
18
18
|
= Changelog
|
19
|
+
* 0.8.1
|
20
|
+
* Bug-Fix: methods insertRowBelow and insertCellAfter did not consider repetitions of previous element
|
19
21
|
* 0.8.0
|
20
22
|
* new function
|
21
23
|
* insertColumn
|
@@ -78,18 +80,25 @@
|
|
78
80
|
= What you must know
|
79
81
|
When you open a (new) spreadsheet in an application like OpenOffice.org, you'll see an infinity of empty cells and
|
80
82
|
might be tempted to assume that all these cells actually "exist" in the underlying file format/XML-structure.
|
81
|
-
This is not the case ! A "newly born" spreadsheet does not contain even a single cell ! They're created on demand
|
82
|
-
with
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
83
|
+
This is not the case ! A "newly born" spreadsheet does not contain even a single cell ! They're created on demand.
|
84
|
+
That is: If you write a cell with coordinates (10,10) into a new sheet only 2 rows and 2 cells are created
|
85
|
+
* an empty row with a repetition-attribute of 9 ( -> visible as row 1 to 9)
|
86
|
+
* a second row (visible on line 10)
|
87
|
+
* a single cell in the second row with a repetition-attribute of 9 ( -> visible as cells 1 to 9 in line 10)
|
88
|
+
* a single cell after the previous cell ( -> visible as cell 10 in line 10)
|
89
|
+
Things get complicated when you insert one or more rows, but we won't delve into implementation details here.
|
90
|
+
Suffice it to say, that
|
91
|
+
* if a single cell in a row has a visible value, the row as well as the cell 'exist' in the former sense, i.e.
|
92
|
+
they're definitely found by the routines get(Next|Previous)Existent(Row|Cell).
|
93
|
+
* the opposite does not apply: If a cell or row is visibly empty it COULD exist (and therefore be detectetd by
|
94
|
+
the former routines) or not. That is: When using the 'fast routines' you will from time to time stumble over
|
95
|
+
cells and rows not bearing any value, but nevertheless existing and are well advised to verify the return-values !
|
96
|
+
|
87
97
|
This is very important for using the interface appropriately: All routines matching 'Existent' merely return "living"
|
88
|
-
cells, while all other routines bearing a "get|Get" create a row or cell if necessary
|
89
|
-
within the new boundaries).
|
98
|
+
cells, while all other routines bearing a "get|Get" create a row or cell if necessary.
|
90
99
|
In other words: Use
|
91
100
|
* getNextExistentRow, getPreviousExistentRow, getNextExistentCell, getPreviousExistentCell
|
92
|
-
whenever you just want to read values you already have (seemlessly skipping visibly emtpy lines and columns) and
|
101
|
+
whenever you just want to read values you already have (seemlessly skipping most but not all visibly emtpy lines and columns) and
|
93
102
|
* getCell, writeGetCell and writeGetCellFromRow whenever you want a cell to be created if it does not exist (which
|
94
103
|
is undoubtedly the case, when you want to write to it or assign it a style) !
|
95
104
|
The first return nil, if an element does not exist yet, the second always return the desired element.
|
@@ -297,51 +306,51 @@
|
|
297
306
|
|
298
307
|
= Example 0.8.0
|
299
308
|
|
300
|
-
|
301
|
-
#
|
302
|
-
#
|
303
|
-
#
|
304
|
-
# #
|
305
|
-
# require 'rubygems'
|
306
|
-
# require 'rods'
|
309
|
+
#!/usr/bin/ruby
|
310
|
+
# coding: UTF-8
|
311
|
+
#
|
312
|
+
# Author: Dr. Heinz Breinlinger
|
307
313
|
#
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
#
|
319
|
-
|
320
|
-
|
321
|
-
|
314
|
+
require 'rubygems'
|
315
|
+
require 'rods'
|
316
|
+
|
317
|
+
mySheet=Rods.new("Template.ods")
|
318
|
+
1.upto(3){ |row|
|
319
|
+
1.upto(4){ |col|
|
320
|
+
mySheet.writeCell(row,col,"time","13:47")
|
321
|
+
}
|
322
|
+
}
|
323
|
+
#-----------------------------------------------------
|
324
|
+
# inserting new column -> shifting existing columns
|
325
|
+
#-----------------------------------------------------
|
326
|
+
mySheet.insertColumn(3)
|
327
|
+
1.upto(3){ |row|
|
328
|
+
mySheet.writeCell(row,3,"string","o' clock")
|
329
|
+
}
|
330
|
+
mySheet.saveAs("Test7.ods")
|
322
331
|
|
323
332
|
= Example 0.7.5
|
324
333
|
|
325
|
-
|
326
|
-
#
|
327
|
-
#
|
328
|
-
#
|
329
|
-
# #
|
330
|
-
# require 'rubygems'
|
331
|
-
# require 'rods'
|
334
|
+
#!/usr/bin/ruby
|
335
|
+
# coding: UTF-8
|
336
|
+
#
|
337
|
+
# Author: Dr. Heinz Breinlinger
|
332
338
|
#
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
339
|
+
require 'rubygems'
|
340
|
+
require 'rods'
|
341
|
+
|
342
|
+
mySheet=Rods.new("Template.ods")
|
343
|
+
mySheet.writeCell(1,1,"string","oneOne")
|
344
|
+
mySheet.writeCell(1,2,"string","oneTwo")
|
345
|
+
mySheet.writeCell(2,1,"string","twoOne") # finally becomes cell 3,1
|
346
|
+
mySheet.writeCell(2,2,"string","twoTwo") # finally becomes cell 3,2
|
347
|
+
row=mySheet.getRow(1)
|
348
|
+
newRow=mySheet.insertRowBelow(row)
|
349
|
+
mySheet.writeCell(2,1,"string","twoNewOne")
|
350
|
+
cell=mySheet.writeGetCell(2,2,"string","moved") # finally becomes cell "2,3"
|
351
|
+
mySheet.insertCellBefore(cell)
|
352
|
+
mySheet.writeCell(2,2,"string","twoNewTwoNew") # new cell "2,2"
|
353
|
+
mySheet.saveAs("Test6.ods")
|
345
354
|
|
346
355
|
= Example 0.7.0
|
347
356
|
|
@@ -483,6 +492,9 @@
|
|
483
492
|
# allow the XML-Parser to just continue from the "adjacent" node and
|
484
493
|
# return the previsous/next element without having to start from the top-node
|
485
494
|
# of the document over and over again !
|
495
|
+
# Caveat: According to the explanation above, you definitely know, that a cell/row
|
496
|
+
# exist, if they bear a value; if they don't, it depends on the sheets history,
|
497
|
+
# whether these are 'alive' and therefore accessible by the afore functions or not !
|
486
498
|
#---------------------------------------------------------------------------------
|
487
499
|
while(row=mySheet.getNextExistentRow(row))
|
488
500
|
i+=1
|
data/Rakefile
CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
|
|
2
2
|
require 'rake'
|
3
3
|
require 'echoe'
|
4
4
|
|
5
|
-
Echoe.new('rods', '0.8.
|
5
|
+
Echoe.new('rods', '0.8.1') do |p|
|
6
6
|
p.description = "OpenOffice.org oocalc: Fast automated batch-processing of spreadsheets (*.ods) conforming to Open Document Format v1.1. used by e.g. OpenOffice.org and LibreOffice. Please see screenshot and Rdoc-Documentation at http://ruby.homelinux.com/ruby/rods/. You can contact me at rods.ruby@online.de (and tell me about your experiences or drop me a line, if you like it ;-)"
|
7
7
|
p.summary = "Automation of OpenOffice/LibreOffice by batch-processing of spreadsheets conforming to Open Document v1.1"
|
8
8
|
p.url = "http://ruby.homelinux.com/ruby/rods/"
|
data/lib/rods.rb
CHANGED
@@ -435,7 +435,6 @@ class Rods
|
|
435
435
|
#-------------------------------------------------------------------------
|
436
436
|
def renameTable(oldName,newName)
|
437
437
|
die("renameTable: table '#{oldName}' does not exist") unless (@tables.has_key?(oldName))
|
438
|
-
# die("renameTable: table '#{oldName}' cannot be renamed as it is the current table !") if (oldName == @currentTableName)
|
439
438
|
#------------------------------------------------------
|
440
439
|
# XML-Tree anpassen
|
441
440
|
#------------------------------------------------------
|
@@ -810,11 +809,11 @@ class Rods
|
|
810
809
|
else
|
811
810
|
text=textElement.text
|
812
811
|
if(! text)
|
813
|
-
|
812
|
+
text=""
|
814
813
|
end
|
815
814
|
type=cell.attributes["office:value-type"]
|
816
815
|
if(! type)
|
817
|
-
|
816
|
+
type="string"
|
818
817
|
end
|
819
818
|
text=normalizeText(text,type)
|
820
819
|
return text,type
|
@@ -2599,12 +2598,12 @@ class Rods
|
|
2599
2598
|
# Also consider that you have to search for the external (i.e. visible)
|
2600
2599
|
# represenation of a cell's content, not it's internal computational value.
|
2601
2600
|
# For instance, when looking for a currency value of 1525 (that is shown as
|
2602
|
-
# '1.525
|
2601
|
+
# '1.525 EUR'), you'll have to code
|
2603
2602
|
#
|
2604
|
-
#
|
2605
|
-
#
|
2606
|
-
#
|
2607
|
-
#
|
2603
|
+
# result=mySheet.getCellsAndIndicesFor('1[.,]525')
|
2604
|
+
# result.each{ |cellHash|
|
2605
|
+
# puts("Found #{cellHash[:cell] on #{cellHash[:row] - #{cellHash[:col]")
|
2606
|
+
# }
|
2608
2607
|
#-------------------------------------------------------------------------
|
2609
2608
|
def getCellsAndIndicesFor(content)
|
2610
2609
|
die("getCellsAndIndicesFor: 'content' is not of typ String") unless (content.class.to_s == "String")
|
@@ -2776,8 +2775,16 @@ class Rods
|
|
2776
2775
|
def insertCellAfter(cell)
|
2777
2776
|
newCell=createCell(1)
|
2778
2777
|
cell.next_sibling=newCell
|
2778
|
+
#-----------------------------------------------------------------------
|
2779
|
+
# Cave: etwaige Wiederholungen uebertragen
|
2780
|
+
#-----------------------------------------------------------------------
|
2781
|
+
repetitions=cell.attributes["table:number-columns-repeated"]
|
2782
|
+
if(repetitions)
|
2783
|
+
cell.attributes.delete("table:number-columns-repeated")
|
2784
|
+
newCell.next_sibling=createCell(repetitions.to_i)
|
2785
|
+
end
|
2779
2786
|
#-----------------------------------------
|
2780
|
-
# bisherige Tabellenbreite
|
2787
|
+
# bisherige Tabellenbreite ueberschritten ?
|
2781
2788
|
#-----------------------------------------
|
2782
2789
|
lengthOfRow=getNumberOfSiblings(cell)
|
2783
2790
|
if(lengthOfRow > @tables[@currentTableName][WIDTH])
|
@@ -2805,6 +2812,14 @@ class Rods
|
|
2805
2812
|
def insertRowBelow(row)
|
2806
2813
|
newRow=createRow(1)
|
2807
2814
|
row.next_sibling=newRow
|
2815
|
+
#-----------------------------------------------------------------------
|
2816
|
+
# Cave: etwaige Wiederholungen uebertragen
|
2817
|
+
#-----------------------------------------------------------------------
|
2818
|
+
repetitions=row.attributes["table:number-rows-repeated"]
|
2819
|
+
if(repetitions)
|
2820
|
+
row.attributes.delete("table:number-rows-repeated")
|
2821
|
+
newRow.next_sibling=createRow(repetitions.to_i)
|
2822
|
+
end
|
2808
2823
|
return newRow
|
2809
2824
|
end
|
2810
2825
|
##########################################################################
|
@@ -2838,6 +2853,81 @@ class Rods
|
|
2838
2853
|
end
|
2839
2854
|
end
|
2840
2855
|
##########################################################################
|
2856
|
+
# internal: returns cell at index if existent, nil otherwise
|
2857
|
+
# row=getRowIfExists(4)
|
2858
|
+
# if(row)
|
2859
|
+
# cell=getCellIfExists(row,7)
|
2860
|
+
# unless(cell) .....
|
2861
|
+
# end
|
2862
|
+
#-------------------------------------------------------------------------
|
2863
|
+
def getCellIfExists(row,index)
|
2864
|
+
return getElementIfExists(row,CELL,index)
|
2865
|
+
end
|
2866
|
+
##########################################################################
|
2867
|
+
# internal: returns row at index if existent, nil otherwise
|
2868
|
+
# if(mySheet.getRowIfExists(4))
|
2869
|
+
# ........
|
2870
|
+
# end
|
2871
|
+
#-------------------------------------------------------------------------
|
2872
|
+
def getRowIfExists(index)
|
2873
|
+
currentTable=@tables[@currentTableName][NODE]
|
2874
|
+
return getElementIfExists(currentTable,ROW,index)
|
2875
|
+
end
|
2876
|
+
##########################################################################
|
2877
|
+
# internal: examines, whether element of given type (row, cell, column) and index
|
2878
|
+
# exists or not.
|
2879
|
+
# Returns the element or nil if not existent.
|
2880
|
+
#-------------------------------------------------------------------------
|
2881
|
+
def getElementIfExists(parent,type,index)
|
2882
|
+
die("getElementIfExists: invalid type #{type}")
|
2883
|
+
die("getElementIfExists: parent is not a REXML::Element") unless (parent.class.to_s == "REXML::Element")
|
2884
|
+
die("getElementIfExists: index #{index} is not a Fixnum/Integer") unless (index.class.to_s == "Fixnum")
|
2885
|
+
die("getElementIfExists: invalid range for index #{index}") unless (index > 0)
|
2886
|
+
#--------------------------------------------------------------
|
2887
|
+
# Typabhaengige Vorbelegungen
|
2888
|
+
#--------------------------------------------------------------
|
2889
|
+
case type
|
2890
|
+
when CELL
|
2891
|
+
kindOfSelf="table:table-cell"
|
2892
|
+
kindOfParent="table:table-row"
|
2893
|
+
kindOfRepetition="table:number-columns-repeated"
|
2894
|
+
when COLUMN
|
2895
|
+
kindOfSelf="table:table-column"
|
2896
|
+
kindOfParent="table:table"
|
2897
|
+
kindOfRepetition="table:number-columns-repeated"
|
2898
|
+
when ROW
|
2899
|
+
kindOfSelf="table:table-row"
|
2900
|
+
kindOfParent="table:table"
|
2901
|
+
kindOfRepetition="table:number-rows-repeated"
|
2902
|
+
else
|
2903
|
+
die("getElementIfExists: invalid type #{type}")
|
2904
|
+
end
|
2905
|
+
#--------------------------------------------------------------
|
2906
|
+
# Ist Kind-Element mit Index in Vater-Element vorhanden ?
|
2907
|
+
#--------------------------------------------------------------
|
2908
|
+
i=0
|
2909
|
+
parent.elements.each(kindOfSelf){ |child|
|
2910
|
+
i+=1
|
2911
|
+
#----------------------------------------------------------
|
2912
|
+
# Index ueberschritten ? -> Ruecksprung mit nil
|
2913
|
+
# Index gefunden ? -> Rueckgabe des Elementes
|
2914
|
+
# sonst: etwaige Wiederholungen zaehlen
|
2915
|
+
#----------------------------------------------------------
|
2916
|
+
if (i > index)
|
2917
|
+
return nil
|
2918
|
+
elsif(i == index)
|
2919
|
+
tell("getElementIfExists: Found element #{type} at index #{index}")
|
2920
|
+
return child
|
2921
|
+
elsif(repetition=child.attributes[kindOfRepetition])
|
2922
|
+
index+=repetition.to_i-1 # '-1', da aktuelles Element ebenfalls als Wiederholung zaehlt
|
2923
|
+
end
|
2924
|
+
}
|
2925
|
+
#-------------------------------------------------------
|
2926
|
+
# Index liegt ausserhalb vorhandener Kind-Elemente
|
2927
|
+
#-------------------------------------------------------
|
2928
|
+
return nil
|
2929
|
+
end
|
2930
|
+
##########################################################################
|
2841
2931
|
# internal: Opens zip-file
|
2842
2932
|
#-------------------------------------------------------------------------
|
2843
2933
|
def open(file)
|
@@ -2857,7 +2947,7 @@ class Rods
|
|
2857
2947
|
:getCellFromRow, :getCell, :getRow, :renameTable, :setCurrentTable,
|
2858
2948
|
:insertTable, :deleteTable, :readCellFromRow, :readCell, :setAttributes, :writeStyleAbbr,
|
2859
2949
|
:setStyle, :printOfficeStyles, :printAutoStyles, :getNextExistentRow, :getPreviousExistentRow,
|
2860
|
-
|
2950
|
+
:getNextExistentCell, :getPreviousExistentCell, :insertTableAfter, :insertTableBefore,
|
2861
2951
|
:writeComment, :save, :saveAs, :initialize, :writeText, :getCellsAndIndicesFor,
|
2862
2952
|
:insertRowBelow, :insertRowAbove, :insertCellBefore, :insertCellAfter, :insertColumn
|
2863
2953
|
|
@@ -2868,5 +2958,5 @@ class Rods
|
|
2868
2958
|
:getAppropriateStyle, :checkStyleAttributes, :insertStyleAttributes, :cloneNode,
|
2869
2959
|
:writeStyle, :writeStyleXml, :style2Hash, :writeDefaultStyles, :writeXml,
|
2870
2960
|
:internalizeFormula, :getColorPalette, :open, :printStyles, :insertTableBeforeAfter,
|
2871
|
-
:insertColumnBefore
|
2961
|
+
:insertColumnBefore, :getElementIfExists, :getRowIfExists, :getCellIfExists
|
2872
2962
|
end # Klassenende
|
data/rods.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{rods}
|
5
|
-
s.version = "0.8.
|
5
|
+
s.version = "0.8.1"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Dr. Heinz Breinlinger"]
|
@@ -15,11 +15,10 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Rods", "--main", "README"]
|
16
16
|
s.require_paths = ["lib"]
|
17
17
|
s.rubyforge_project = %q{rods}
|
18
|
-
s.rubygems_version = %q{1.
|
18
|
+
s.rubygems_version = %q{1.4.2}
|
19
19
|
s.summary = %q{Automation of OpenOffice/LibreOffice by batch-processing of spreadsheets conforming to Open Document v1.1}
|
20
20
|
|
21
21
|
if s.respond_to? :specification_version then
|
22
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
23
22
|
s.specification_version = 3
|
24
23
|
|
25
24
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rods
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 61
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 8
|
9
|
-
-
|
10
|
-
version: 0.8.
|
9
|
+
- 1
|
10
|
+
version: 0.8.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Dr. Heinz Breinlinger
|
@@ -70,7 +70,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
70
70
|
requirements: []
|
71
71
|
|
72
72
|
rubyforge_project: rods
|
73
|
-
rubygems_version: 1.
|
73
|
+
rubygems_version: 1.4.2
|
74
74
|
signing_key:
|
75
75
|
specification_version: 3
|
76
76
|
summary: Automation of OpenOffice/LibreOffice by batch-processing of spreadsheets conforming to Open Document v1.1
|