rods 0.8.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/README +61 -49
  2. data/Rakefile +1 -1
  3. data/lib/rods.rb +101 -11
  4. data/rods.gemspec +2 -3
  5. 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 along
82
- with all other cells of lesser x- or y-coordinate.
83
- That is: If you write a cell with coordinates (10,10) all cells from (1,1) to (10,10)
84
- spring into existence or vice versa: If the cell farthest down the sheet and farthest to the right
85
- having a visible value has coordinates (90,87), then all cells from row 1-90 and column 1-87 exist,
86
- but no cell out of this virutal rectangle is "alive".
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 (and implicitly all other cells
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
- # #!/usr/bin/ruby
301
- # # coding: UTF-8
302
- # #
303
- # # Author: Dr. Heinz Breinlinger
304
- # #
305
- # require 'rubygems'
306
- # require 'rods'
309
+ #!/usr/bin/ruby
310
+ # coding: UTF-8
311
+ #
312
+ # Author: Dr. Heinz Breinlinger
307
313
  #
308
- # mySheet=Rods.new("Template.ods")
309
- # 1.upto(3){ |row|
310
- # 1.upto(4){ |col|
311
- # mySheet.writeCell(row,col,"time","13:47")
312
- # }
313
- # }
314
- # #-----------------------------------------------------
315
- # # inserting new column -> shifting existing columns
316
- # #-----------------------------------------------------
317
- # mySheet.insertColumn(3)
318
- # 1.upto(3){ |row|
319
- # mySheet.writeCell(row,3,"string","o' clock")
320
- # }
321
- # mySheet.saveAs("Test7.ods")
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
- # #!/usr/bin/ruby
326
- # # coding: UTF-8
327
- # #
328
- # # Author: Dr. Heinz Breinlinger
329
- # #
330
- # require 'rubygems'
331
- # require 'rods'
334
+ #!/usr/bin/ruby
335
+ # coding: UTF-8
336
+ #
337
+ # Author: Dr. Heinz Breinlinger
332
338
  #
333
- # mySheet=Rods.new("Template.ods")
334
- # mySheet.writeCell(1,1,"string","oneOne")
335
- # mySheet.writeCell(1,2,"string","oneTwo")
336
- # mySheet.writeCell(2,1,"string","twoOne") # finally becomes cell 3,1
337
- # mySheet.writeCell(2,2,"string","twoTwo") # finally becomes cell 3,2
338
- # row=mySheet.getRow(1)
339
- # newRow=mySheet.insertRowBelow(row)
340
- # mySheet.writeCell(2,1,"string","twoNewOne")
341
- # cell=mySheet.writeGetCell(2,2,"string","moved") # finally becomes cell "2,3"
342
- # mySheet.insertCellBefore(cell)
343
- # mySheet.writeCell(2,2,"string","twoNewTwoNew") # new cell "2,2"
344
- # mySheet.saveAs("Test6.ods")
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.0') do |p|
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/"
@@ -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
- text=""
812
+ text=""
814
813
  end
815
814
  type=cell.attributes["office:value-type"]
816
815
  if(! type)
817
- type="string"
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 ', you'll have to code
2601
+ # '1.525 EUR'), you'll have to code
2603
2602
  #
2604
- # result=mySheet.getCellsAndIndicesFor('1[.,]525')
2605
- # result.each{ |cellHash|
2606
- # puts("Found #{cellHash[:cell] on #{cellHash[:row] - #{cellHash[:col]")
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 überschritten ?
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
- :getNextExistentCell, :getPreviousExistentCell, :insertTableAfter, :insertTableBefore,
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
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{rods}
5
- s.version = "0.8.0"
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.3.7}
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: 63
5
- prerelease: false
4
+ hash: 61
5
+ prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 8
9
- - 0
10
- version: 0.8.0
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.3.7
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