rods 0.8.1 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest +1 -0
- data/README +135 -0
- data/Rakefile +1 -1
- data/lib/rods.rb +368 -49
- data/rods.gemspec +4 -3
- metadata +7 -7
data/Manifest
CHANGED
data/README
CHANGED
@@ -16,6 +16,11 @@
|
|
16
16
|
Licensed under the same terms as Ruby. No warranty is provided.
|
17
17
|
|
18
18
|
= Changelog
|
19
|
+
* 0.9.0
|
20
|
+
* added new methods
|
21
|
+
* insertRow, insertCell, insertCellFromRow, deleteCellBefore, deleteCellAfter, deleteCell, deleteCellFromRow,
|
22
|
+
deleteRowAbove, deleteRowBelow, deleteRow, deleteColumn, deleteRow2, deleteCell2
|
23
|
+
cf. Examples 0.9.0 a-e and read chapter "Caveat" below for performance-considerations !
|
19
24
|
* 0.8.1
|
20
25
|
* Bug-Fix: methods insertRowBelow and insertCellAfter did not consider repetitions of previous element
|
21
26
|
* 0.8.0
|
@@ -304,6 +309,134 @@
|
|
304
309
|
end
|
305
310
|
end
|
306
311
|
|
312
|
+
= Example 0.9.0 a
|
313
|
+
|
314
|
+
#!/usr/bin/ruby
|
315
|
+
# coding: UTF-8
|
316
|
+
#
|
317
|
+
# Author: Dr. Heinz Breinlinger
|
318
|
+
#
|
319
|
+
require 'rubygems'
|
320
|
+
require 'rods'
|
321
|
+
|
322
|
+
mySheet=Rods.new("Template.ods")
|
323
|
+
1.upto(3){ |row|
|
324
|
+
1.upto(4){ |col|
|
325
|
+
mySheet.writeCell(row,col,"time","13:47")
|
326
|
+
}
|
327
|
+
}
|
328
|
+
mySheet.insertColumn(3)
|
329
|
+
1.upto(3){ |row|
|
330
|
+
mySheet.writeCell(row,3,"string","o' clock")
|
331
|
+
}
|
332
|
+
mySheet.insertRow(2)
|
333
|
+
cell=mySheet.insertCell(3,3)
|
334
|
+
mySheet.writeText(cell,"string","insertCell")
|
335
|
+
row=mySheet.getRow(4)
|
336
|
+
row=mySheet.insertRowAbove(row)
|
337
|
+
mySheet.writeCell(4,1,"string","Willi")
|
338
|
+
cell=mySheet.insertCellFromRow(row,1)
|
339
|
+
mySheet.writeText(cell,"string","Supi")
|
340
|
+
mySheet.saveAs("Test8.ods")
|
341
|
+
|
342
|
+
= Example 0.9.0 b
|
343
|
+
|
344
|
+
#!/usr/bin/ruby
|
345
|
+
# coding: UTF-8
|
346
|
+
#
|
347
|
+
# Author: Dr. Heinz Breinlinger
|
348
|
+
#
|
349
|
+
require 'rubygems'
|
350
|
+
require 'rods'
|
351
|
+
|
352
|
+
mySheet=Rods.new("Template.ods")
|
353
|
+
mySheet.writeCell(1,1,"string","oneone")
|
354
|
+
cell=mySheet.writeGetCell(1,2,"string","onetwo")
|
355
|
+
mySheet.deleteCellBefore(cell)
|
356
|
+
cell=mySheet.writeGetCell(1,5,"string","onefive")
|
357
|
+
mySheet.deleteCellBefore(cell)
|
358
|
+
|
359
|
+
cellOne=mySheet.writeGetCell(5,1,"string","fiveone")
|
360
|
+
cellFive=mySheet.writeGetCell(5,5,"string","fivefive")
|
361
|
+
cellSix=mySheet.writeGetCell(5,6,"string","fivesix")
|
362
|
+
cellNine=mySheet.writeGetCell(5,9,"string","fivenine")
|
363
|
+
mySheet.deleteCellAfter(cellOne)
|
364
|
+
mySheet.deleteCellAfter(cellFive)
|
365
|
+
cell=mySheet.getCell(5,4)
|
366
|
+
mySheet.deleteCellBefore(cell)
|
367
|
+
cell=mySheet.getCell(5,4)
|
368
|
+
mySheet.deleteCellAfter(cell)
|
369
|
+
mySheet.deleteCell(5,2)
|
370
|
+
mySheet.deleteCell(5,3)
|
371
|
+
row=mySheet.getRow(5)
|
372
|
+
mySheet.deleteRowAbove(row)
|
373
|
+
mySheet.insertRow(2)
|
374
|
+
mySheet.insertRow(2)
|
375
|
+
row=mySheet.getRow(2)
|
376
|
+
mySheet.deleteRowBelow(row)
|
377
|
+
row=mySheet.getRow(1)
|
378
|
+
mySheet.deleteRowBelow(row)
|
379
|
+
row=mySheet.getRow(2)
|
380
|
+
mySheet.deleteRowBelow(row)
|
381
|
+
mySheet.deleteRow(2)
|
382
|
+
mySheet.deleteRow(1)
|
383
|
+
mySheet.deleteRow(1)
|
384
|
+
mySheet.saveAs("Test9.ods")
|
385
|
+
|
386
|
+
= Example 0.9.0 c
|
387
|
+
|
388
|
+
#!/usr/bin/ruby
|
389
|
+
# coding: UTF-8
|
390
|
+
#
|
391
|
+
# Author: Dr. Heinz Breinlinger
|
392
|
+
#
|
393
|
+
require 'rubygems'
|
394
|
+
require 'rods'
|
395
|
+
|
396
|
+
mySheet=Rods.new("Konten.ods")
|
397
|
+
startRow=mySheet.getRow(11)
|
398
|
+
i=0
|
399
|
+
while(row=mySheet.getNextExistentRow(startRow))
|
400
|
+
i+=1
|
401
|
+
puts("#{i}")
|
402
|
+
mySheet.deleteRow2(row)
|
403
|
+
end
|
404
|
+
mySheet.saveAs("Test10.ods")
|
405
|
+
|
406
|
+
= Example 0.9.0 d
|
407
|
+
|
408
|
+
#!/usr/bin/ruby
|
409
|
+
# coding: UTF-8
|
410
|
+
#
|
411
|
+
# Author: Dr. Heinz Breinlinger
|
412
|
+
#
|
413
|
+
require 'rubygems'
|
414
|
+
require 'rods'
|
415
|
+
|
416
|
+
mySheet=Rods.new("Konten.ods")
|
417
|
+
mySheet.deleteColumn(8)
|
418
|
+
mySheet.saveAs("Test11.ods")
|
419
|
+
|
420
|
+
= Example 0.9.0 e
|
421
|
+
|
422
|
+
#!/usr/bin/ruby
|
423
|
+
# coding: UTF-8
|
424
|
+
#
|
425
|
+
# Author: Dr. Heinz Breinlinger
|
426
|
+
#
|
427
|
+
require 'rubygems'
|
428
|
+
require 'rods'
|
429
|
+
|
430
|
+
mySheet=Rods.new("Konten.ods")
|
431
|
+
startCell=mySheet.getCell(12,1)
|
432
|
+
i=0
|
433
|
+
while(cell=mySheet.getNextExistentCell(startCell))
|
434
|
+
i+=1
|
435
|
+
puts("#{i}")
|
436
|
+
mySheet.deleteCell2(cell)
|
437
|
+
end
|
438
|
+
mySheet.saveAs("Test12.ods")
|
439
|
+
|
307
440
|
= Example 0.8.0
|
308
441
|
|
309
442
|
#!/usr/bin/ruby
|
@@ -516,6 +649,8 @@
|
|
516
649
|
On the ATOM-Nettop I developed the gem, even the first script above took just 2-3 seconds and on my Core-i7-Notebook it was finished so quickly
|
517
650
|
that I supposed it had halted on an immediate error, so: don't be concerned and just experiment :-).
|
518
651
|
|
652
|
+
The same considerations apply for the family of 'delete'-functions added in version 0.9.0 ! See the examples above.
|
653
|
+
|
519
654
|
= Standards
|
520
655
|
* Open Document Format for Office Applications (Open Document) v1.1 based on OpenOffice.org (OOo)
|
521
656
|
* http://www.oasis-open.org/specs/#opendocumentv1.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.
|
5
|
+
Echoe.new('rods', '0.9.0') 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
@@ -37,6 +37,7 @@ class Rods
|
|
37
37
|
AFTER="after"
|
38
38
|
INDEX="index"
|
39
39
|
NUMBER="number"
|
40
|
+
BOTH="both"
|
40
41
|
WIDTHEXCEEDED="exceeded"
|
41
42
|
##########################################################################
|
42
43
|
# Convenience-function to switch the default-style for the display of
|
@@ -259,6 +260,8 @@ class Rods
|
|
259
260
|
# The child is created if it does not exist.
|
260
261
|
#------------------------------------------------------------------------
|
261
262
|
def getChildByIndex(parent,type,index)
|
263
|
+
die("getChildByIndex: 'parent' #{parent} is not a node") unless (parent.class.to_s == "REXML::Element")
|
264
|
+
die("getChildByIndex: 'index' #{index} is not a Fixnum") unless (index.class.to_s == "Fixnum")
|
262
265
|
i=0
|
263
266
|
lastElement=nil
|
264
267
|
#----------------------------------------------------------------------
|
@@ -2151,8 +2154,8 @@ class Rods
|
|
2151
2154
|
##########################################################################
|
2152
2155
|
# internal: Helper-Tool: Prints out all styles of given node in an indented ASCII-notation
|
2153
2156
|
#------------------------------------------------------------------------
|
2154
|
-
def printStyles(
|
2155
|
-
|
2157
|
+
def printStyles(startNode,indent)
|
2158
|
+
startNode.elements.each("*"){ |element|
|
2156
2159
|
#------------------------------------------
|
2157
2160
|
# Tag extrahieren (Standard-Tag-Zeichen nach '<')
|
2158
2161
|
#------------------------------------------
|
@@ -2541,9 +2544,19 @@ class Rods
|
|
2541
2544
|
# to start from top-node of document to find row !
|
2542
2545
|
# Returns previous row as a REXML::Element or nil if no element exists.
|
2543
2546
|
# Cf. explanation in README !
|
2547
|
+
#
|
2544
2548
|
#------------------------------------------------------------------------
|
2545
2549
|
def getPreviousExistentRow(row)
|
2546
|
-
|
2550
|
+
#----------------------------------------------------------------------
|
2551
|
+
# Cave: table:table-row und table:table-column sind Siblings !!!!
|
2552
|
+
# Letztere duerfen jedoch NICHT zurueckgegeben werden
|
2553
|
+
#----------------------------------------------------------------------
|
2554
|
+
previousSibling=row.previous_sibling
|
2555
|
+
if(previousSibling && previousSibling.elements["self::table:table-row"])
|
2556
|
+
return previousSibling
|
2557
|
+
else
|
2558
|
+
return nil
|
2559
|
+
end
|
2547
2560
|
end
|
2548
2561
|
##########################################################################
|
2549
2562
|
# Fast Routine to get the next cell, because XML-Parser does not have
|
@@ -2631,7 +2644,7 @@ class Rods
|
|
2631
2644
|
unless (cell)
|
2632
2645
|
die("getCellsAndIndicesFor: internal error: Could not extract parent-cell of textNode with #{content}")
|
2633
2646
|
end
|
2634
|
-
colIndex=
|
2647
|
+
colIndex=getIndex(cell)
|
2635
2648
|
#-----------------------------------------------------
|
2636
2649
|
# Zeile und Zeilenindex ermitteln
|
2637
2650
|
#-----------------------------------------------------
|
@@ -2639,7 +2652,7 @@ class Rods
|
|
2639
2652
|
unless (row)
|
2640
2653
|
die("getCellsAndIndicesFor: internal error: Could not extract parent-row of textNode with #{content}")
|
2641
2654
|
end
|
2642
|
-
rowIndex=
|
2655
|
+
rowIndex=getIndex(row)
|
2643
2656
|
result[i][:cell]=cell
|
2644
2657
|
result[i][:row]=rowIndex
|
2645
2658
|
result[i][:col]=colIndex
|
@@ -2651,32 +2664,42 @@ class Rods
|
|
2651
2664
|
end
|
2652
2665
|
##########################################################################
|
2653
2666
|
# internal: Wrapper for
|
2654
|
-
#
|
2667
|
+
# getIndexAndOrNumber(node,NUMBER)
|
2655
2668
|
#-------------------------------------------------------------------------
|
2656
2669
|
def getNumberOfSiblings(node)
|
2657
|
-
return
|
2670
|
+
return getIndexAndOrNumber(node,NUMBER)
|
2658
2671
|
end
|
2659
2672
|
##########################################################################
|
2660
2673
|
# internal: Wrapper for
|
2661
|
-
#
|
2674
|
+
# getIndexAndOrNumber(node,INDEX)
|
2662
2675
|
#-------------------------------------------------------------------------
|
2663
|
-
def
|
2664
|
-
return
|
2676
|
+
def getIndex(node)
|
2677
|
+
return getIndexAndOrNumber(node,INDEX)
|
2678
|
+
end
|
2679
|
+
##########################################################################
|
2680
|
+
# internal: Wrapper for
|
2681
|
+
# getIndexAndOrNumber(node,BOTH)
|
2682
|
+
#-------------------------------------------------------------------------
|
2683
|
+
def getIndexAndNumber(node)
|
2684
|
+
return getIndexAndOrNumber(node,BOTH)
|
2665
2685
|
end
|
2666
2686
|
##########################################################################
|
2667
2687
|
# internal: Calculates index (in the sense of spreadsheet, NOT XML) of
|
2668
2688
|
# given element (row, cell or column as REXML::Element) within the
|
2669
2689
|
# corresponding parent-element (table or row) or the number of siblings
|
2670
|
-
# of the same kind - depending on
|
2690
|
+
# of the same kind or both - depending on the flag given.
|
2691
|
+
#
|
2692
|
+
# Cave: In case of flag 'BOTH' the method returns TWO values !
|
2671
2693
|
#
|
2672
|
-
# index=
|
2673
|
-
# numColumns=
|
2694
|
+
# index=getIndexAndOrNumber(row,INDEX) # -> Line-number within table
|
2695
|
+
# numColumns=getIndexAndOrNumber(column,NUMBER) # number of columns
|
2696
|
+
# index,numColumns=getIndexAndOrNumber(row,BOTH) # Line-number and total number of lines
|
2674
2697
|
#-------------------------------------------------------------------------
|
2675
|
-
def
|
2676
|
-
die("
|
2698
|
+
def getIndexAndOrNumber(node,flag)
|
2699
|
+
die("getIndexAndOrNumber: passed node '#{node}' is not a REXML::Element") \
|
2677
2700
|
unless (node.class.to_s == "REXML::Element")
|
2678
|
-
die("
|
2679
|
-
unless (flag == NUMBER || flag == INDEX)
|
2701
|
+
die("getIndexAndOrNumber: internal error: invalid flag '#{flag}'") \
|
2702
|
+
unless (flag == NUMBER || flag == INDEX || flag == BOTH)
|
2680
2703
|
#--------------------------------------------------------------
|
2681
2704
|
# Typabhaengige Vorbelegungen
|
2682
2705
|
#--------------------------------------------------------------
|
@@ -2693,49 +2716,55 @@ class Rods
|
|
2693
2716
|
kindOfParent="table:table"
|
2694
2717
|
kindOfRepetition="table:number-rows-repeated"
|
2695
2718
|
else
|
2696
|
-
die("
|
2719
|
+
die("getIndexAndOrNumber: internal error: passed element '#{node}' is neither cell, nor row or column")
|
2697
2720
|
end
|
2698
2721
|
#--------------------------------------------------------------
|
2699
2722
|
# Zugehoeriges Vater-Element ermitteln
|
2700
2723
|
#--------------------------------------------------------------
|
2701
2724
|
parent=node.elements["ancestor::"+kindOfParent]
|
2702
2725
|
unless (parent)
|
2703
|
-
die("
|
2726
|
+
die("getIndexAndOrNumber: internal error: Could not extract parent of #{node}")
|
2704
2727
|
end
|
2705
2728
|
#--------------------------------------------------------------
|
2706
2729
|
# Index des Kind-Elements innerhalb Vater-Element oder
|
2707
|
-
# Gesamtzahl der
|
2730
|
+
# Gesamtzahl der Items ermitteln
|
2708
2731
|
#--------------------------------------------------------------
|
2709
|
-
index=0
|
2732
|
+
index=number=0
|
2710
2733
|
parent.elements.each(kindOfSelf){ |child|
|
2711
|
-
|
2734
|
+
number+=1
|
2712
2735
|
#-----------------------------------------------
|
2713
|
-
#
|
2714
|
-
#
|
2715
|
-
# verwerfen und weiterzaehlen
|
2736
|
+
# Kind-Element gefunden ? -> Index festhalten,
|
2737
|
+
# je nach Flag Ruecksprung oder weiterzaehlen
|
2716
2738
|
#-----------------------------------------------
|
2717
|
-
if(
|
2718
|
-
|
2739
|
+
if(child == node)
|
2740
|
+
if(flag == INDEX)
|
2741
|
+
return number
|
2742
|
+
elsif(flag == BOTH)
|
2743
|
+
index=number
|
2744
|
+
end
|
2719
2745
|
#-----------------------------------------------
|
2720
2746
|
# Wiederholungen zaehlen
|
2721
2747
|
# Cave: Aktuelles Element selbst zaehlt ebenfalls als Wiederholung
|
2722
2748
|
# => um 1 dekrementieren
|
2723
2749
|
#-----------------------------------------------
|
2724
2750
|
elsif(repetition=child.attributes[kindOfRepetition])
|
2725
|
-
|
2751
|
+
number+=repetition.to_i-1
|
2726
2752
|
end
|
2727
2753
|
}
|
2728
2754
|
if(flag == INDEX)
|
2729
|
-
die("
|
2755
|
+
die("getIndexAndOrNumber: internal error: Could not calculate number of element #{node}")
|
2756
|
+
elsif(flag == NUMBER)
|
2757
|
+
return number
|
2730
2758
|
else
|
2731
|
-
return index
|
2759
|
+
return index,number
|
2732
2760
|
end
|
2733
2761
|
end
|
2734
2762
|
##########################################################################
|
2735
|
-
# internal: Inserts a new header-column before the given column thereby
|
2736
|
-
# shifting existing
|
2763
|
+
# internal: Inserts a new header-column before the given header-column thereby
|
2764
|
+
# shifting existing header-columns
|
2737
2765
|
#-------------------------------------------------------------------------
|
2738
|
-
def
|
2766
|
+
def insertColumnBeforeInHeader(column)
|
2767
|
+
die("insertColumnBeforeInHeader: column #{column} is not a REXML::Element") unless (column.class.to_s == "REXML::Element")
|
2739
2768
|
newColumn=createColumn(1)
|
2740
2769
|
column.previous_sibling=newColumn
|
2741
2770
|
#-----------------------------------------
|
@@ -2749,11 +2778,218 @@ class Rods
|
|
2749
2778
|
return newColumn
|
2750
2779
|
end
|
2751
2780
|
##########################################################################
|
2781
|
+
# Delets the cell to the right of the given cell
|
2782
|
+
#
|
2783
|
+
# cell=mySheet.writeGetCell(4,7,"date","16.01.2011")
|
2784
|
+
# mySheet.deleteCellAfter(cell)
|
2785
|
+
#-------------------------------------------------------------------------
|
2786
|
+
def deleteCellAfter(cell)
|
2787
|
+
die("deleteCellAfter: cell #{cell} is not a REXML::Element") unless (cell.class.to_s == "REXML::Element")
|
2788
|
+
#--------------------------------------------------------
|
2789
|
+
# Entweder Wiederholungsattribut der aktuellen Zelle
|
2790
|
+
# dekrementieren oder ggf. Wiederholungsattribut der
|
2791
|
+
# Folgezelle dekrementieren oder selbige loeschen
|
2792
|
+
#--------------------------------------------------------
|
2793
|
+
repetitions=cell.attributes["table:number-columns-repeated"]
|
2794
|
+
if(repetitions && repetitions.to_i > 1)
|
2795
|
+
cell.attributes["table:number-columns-repeated"]=(repetitions.to_i-1).to_s
|
2796
|
+
else
|
2797
|
+
nextCell=cell.next_sibling
|
2798
|
+
die("deleteCellAfter: cell is already last cell in row") unless (nextCell)
|
2799
|
+
nextRepetitions=nextCell.attributes["table:number-columns-repeated"]
|
2800
|
+
if(nextRepetitions && nextRepetitions.to_i > 1)
|
2801
|
+
nextCell.attributes["table:number-columns-repeated"]=(nextRepetitions.to_i-1).to_s
|
2802
|
+
else
|
2803
|
+
row=cell.elements["ancestor::table:table-row"]
|
2804
|
+
unless (row)
|
2805
|
+
die("deleteCellAfter: internal error: Could not extract parent-row of cell #{cell}")
|
2806
|
+
end
|
2807
|
+
row.elements.delete(nextCell)
|
2808
|
+
end
|
2809
|
+
end
|
2810
|
+
end
|
2811
|
+
##########################################################################
|
2812
|
+
# Delets the row below the given row
|
2813
|
+
#
|
2814
|
+
# row=mySheet.getRow(11)
|
2815
|
+
# mySheet.deleteRowBelow(row)
|
2816
|
+
#-------------------------------------------------------------------------
|
2817
|
+
def deleteRowBelow(row)
|
2818
|
+
die("deleteRowBelow: row #{row} is not a REXML::Element") unless (row.class.to_s == "REXML::Element")
|
2819
|
+
#--------------------------------------------------------
|
2820
|
+
# Entweder Wiederholungsattribut der aktuellen Zeile
|
2821
|
+
# dekrementieren oder ggf. Wiederholungsattribut der
|
2822
|
+
# Folgezeile dekrementieren oder selbige loeschen
|
2823
|
+
#--------------------------------------------------------
|
2824
|
+
repetitions=row.attributes["table:number-rows-repeated"]
|
2825
|
+
if(repetitions && repetitions.to_i > 1)
|
2826
|
+
row.attributes["table:number-rows-repeated"]=(repetitions.to_i-1).to_s
|
2827
|
+
else
|
2828
|
+
nextRow=row.next_sibling
|
2829
|
+
die("deleteRowBelow: row #{row} is already last row in table") unless (nextRow)
|
2830
|
+
nextRepetitions=nextRow.attributes["table:number-rows-repeated"]
|
2831
|
+
if(nextRepetitions && nextRepetitions.to_i > 1)
|
2832
|
+
nextRow.attributes["table:number-rows-repeated"]=(nextRepetitions.to_i-1).to_s
|
2833
|
+
else
|
2834
|
+
table=row.elements["ancestor::table:table"]
|
2835
|
+
unless (table)
|
2836
|
+
die("deleteRowBelow: internal error: Could not extract parent-table of row #{row}")
|
2837
|
+
end
|
2838
|
+
table.elements.delete(nextRow)
|
2839
|
+
end
|
2840
|
+
end
|
2841
|
+
end
|
2842
|
+
##########################################################################
|
2843
|
+
# Delets the cell at the given index in the given row
|
2844
|
+
#
|
2845
|
+
# row=mySheet.getRow(8)
|
2846
|
+
# mySheet.deleteCell(row,9)
|
2847
|
+
#-------------------------------------------------------------------------
|
2848
|
+
def deleteCellFromRow(row,colInd)
|
2849
|
+
die("deleteCell: row #{row} is not a REXML::Element") unless (row.class.to_s == "REXML::Element")
|
2850
|
+
die("deleteCell: index #{colInd} is not a Fixnum/Integer") unless (colInd.class.to_s == "Fixnum")
|
2851
|
+
die("deleteCell: invalid index #{colInd}") unless (colInd > 0)
|
2852
|
+
cell=getCellFromRow(row,colInd+1)
|
2853
|
+
deleteCellBefore(cell)
|
2854
|
+
end
|
2855
|
+
##########################################################################
|
2856
|
+
# Delets the given cell.
|
2857
|
+
#
|
2858
|
+
# 'cell' is a REXML::Element as returned by getCell(cellInd).
|
2859
|
+
#
|
2860
|
+
# startCell=mySheet.getCell(34,1)
|
2861
|
+
# while(cell=mySheet.getNextExistentCell(startCell))
|
2862
|
+
# mySheet.deleteCell2(cell)
|
2863
|
+
# end
|
2864
|
+
#-------------------------------------------------------------------------
|
2865
|
+
def deleteCell2(cell)
|
2866
|
+
die("deleteCell2: cell #{cell} is not a REXML::Element") unless (cell.class.to_s == "REXML::Element")
|
2867
|
+
#-------------------------------------------------------------------
|
2868
|
+
# Entweder Wiederholungszahl dekrementieren oder Zelle loeschen
|
2869
|
+
#-------------------------------------------------------------------
|
2870
|
+
repetitions=cell.attributes["table:number-columuns-repeated"]
|
2871
|
+
if(repetitions && repetitions.to_i > 1)
|
2872
|
+
cell.attributes["table:number-columns-repeated"]=(repetitions.to_i-1).to_s
|
2873
|
+
tell("deleteCell2: decrementing empty cells")
|
2874
|
+
else
|
2875
|
+
row=cell.elements["ancestor::table:table-row"]
|
2876
|
+
unless (row)
|
2877
|
+
die("deleteCell2: internal error: Could not extract parent-row of cell #{cell}")
|
2878
|
+
end
|
2879
|
+
row.elements.delete(cell)
|
2880
|
+
tell("deleteCell2: deleting non-empty cell")
|
2881
|
+
end
|
2882
|
+
end
|
2883
|
+
##########################################################################
|
2884
|
+
# Delets the given row.
|
2885
|
+
#
|
2886
|
+
# 'row' is a REXML::Element as returned by getRow(rowInd).
|
2887
|
+
#
|
2888
|
+
# startRow=mySheet.getRow(12)
|
2889
|
+
# while(row=mySheet.getNextExistentRow(startRow))
|
2890
|
+
# mySheet.deleteRow2(row)
|
2891
|
+
# end
|
2892
|
+
#-------------------------------------------------------------------------
|
2893
|
+
def deleteRow2(row)
|
2894
|
+
die("deleteRow2: row #{row} is not a REXML::Element") unless (row.class.to_s == "REXML::Element")
|
2895
|
+
#-------------------------------------------------------------------
|
2896
|
+
# Entweder Wiederholungszahl dekrementieren oder Zeile loeschen
|
2897
|
+
#-------------------------------------------------------------------
|
2898
|
+
repetitions=row.attributes["table:number-rows-repeated"]
|
2899
|
+
if(repetitions && repetitions.to_i > 1)
|
2900
|
+
row.attributes["table:number-rows-repeated"]=(repetitions.to_i-1).to_s
|
2901
|
+
tell("deleteRow2: decrementing empty rows")
|
2902
|
+
else
|
2903
|
+
table=row.elements["ancestor::table:table"]
|
2904
|
+
unless (table)
|
2905
|
+
die("deleteRow2: internal error: Could not extract parent-table of row #{row}")
|
2906
|
+
end
|
2907
|
+
table.elements.delete(row)
|
2908
|
+
tell("deleteRow2: deleting non-empty row")
|
2909
|
+
end
|
2910
|
+
end
|
2911
|
+
##########################################################################
|
2912
|
+
# Delets the row at the given index
|
2913
|
+
#
|
2914
|
+
# mySheet.deleteRow(7)
|
2915
|
+
#-------------------------------------------------------------------------
|
2916
|
+
def deleteRow(rowInd)
|
2917
|
+
die("deleteRow: index #{rowInd} is not a Fixnum/Integer") unless (rowInd.class.to_s == "Fixnum")
|
2918
|
+
die("deleteRow: invalid index #{rowInd}") unless (rowInd > 0)
|
2919
|
+
row=getRow(rowInd+1)
|
2920
|
+
deleteRowAbove(row)
|
2921
|
+
end
|
2922
|
+
##########################################################################
|
2923
|
+
# Delets the cell at the given indices
|
2924
|
+
#
|
2925
|
+
# mySheet.deleteCell(7,9)
|
2926
|
+
#-------------------------------------------------------------------------
|
2927
|
+
def deleteCell(rowInd,colInd)
|
2928
|
+
die("deleteCell: index #{rowInd} is not a Fixnum/Integer") unless (rowInd.class.to_s == "Fixnum")
|
2929
|
+
die("deleteCell: invalid index #{rowInd}") unless (rowInd > 0)
|
2930
|
+
die("deleteCell: index #{colInd} is not a Fixnum/Integer") unless (colInd.class.to_s == "Fixnum")
|
2931
|
+
die("deleteCell: invalid index #{colInd}") unless (colInd > 0)
|
2932
|
+
tell("deleteCell: deleting cell at #{rowInd}:#{colInd}")
|
2933
|
+
row=getRow(rowInd)
|
2934
|
+
deleteCellFromRow(row,colInd)
|
2935
|
+
end
|
2936
|
+
##########################################################################
|
2937
|
+
# Delets the row above the given row
|
2938
|
+
#
|
2939
|
+
# row=mySheet.getRow(5)
|
2940
|
+
# mySheet.deleteRowAbove(row)
|
2941
|
+
#-------------------------------------------------------------------------
|
2942
|
+
def deleteRowAbove(row)
|
2943
|
+
die("deleteRowAbove: row #{row} is not a REXML::Element") unless (row.class.to_s == "REXML::Element")
|
2944
|
+
#--------------------------------------------------------
|
2945
|
+
# Entweder Wiederholungsattribut der vorherigen Zeile
|
2946
|
+
# dekrementieren oder selbige loeschen
|
2947
|
+
#--------------------------------------------------------
|
2948
|
+
previousRow=row.previous_sibling
|
2949
|
+
die("deleteRowAbove: row is already first row in row") unless (previousRow)
|
2950
|
+
previousRepetitions=previousRow.attributes["table:number-rows-repeated"]
|
2951
|
+
if(previousRepetitions && previousRepetitions.to_i > 1)
|
2952
|
+
previousRow.attributes["table:number-rows-repeated"]=(previousRepetitions.to_i-1).to_s
|
2953
|
+
else
|
2954
|
+
table=row.elements["ancestor::table:table"]
|
2955
|
+
unless (table)
|
2956
|
+
die("deleteRowAbove: internal error: Could not extract parent-table of row #{row}")
|
2957
|
+
end
|
2958
|
+
table.elements.delete(previousRow)
|
2959
|
+
end
|
2960
|
+
end
|
2961
|
+
##########################################################################
|
2962
|
+
# Delets the cell to the left of the given cell
|
2963
|
+
#
|
2964
|
+
# cell=mySheet.writeGetCell(4,7,"formula:currency","=A1+B2")
|
2965
|
+
# mySheet.deleteCellBefore(cell)
|
2966
|
+
#-------------------------------------------------------------------------
|
2967
|
+
def deleteCellBefore(cell)
|
2968
|
+
die("deleteCellBefore: cell #{cell} is not a REXML::Element") unless (cell.class.to_s == "REXML::Element")
|
2969
|
+
#--------------------------------------------------------
|
2970
|
+
# Entweder Wiederholungsattribut der vorherigen Zelle
|
2971
|
+
# dekrementieren oder selbige loeschen
|
2972
|
+
#--------------------------------------------------------
|
2973
|
+
previousCell=cell.previous_sibling
|
2974
|
+
die("deleteCellBefore: cell is already first cell in row") unless (previousCell)
|
2975
|
+
previousRepetitions=previousCell.attributes["table:number-columns-repeated"]
|
2976
|
+
if(previousRepetitions && previousRepetitions.to_i > 1)
|
2977
|
+
previousCell.attributes["table:number-columns-repeated"]=(previousRepetitions.to_i-1).to_s
|
2978
|
+
else
|
2979
|
+
row=cell.elements["ancestor::table:table-row"]
|
2980
|
+
unless (row)
|
2981
|
+
die("deleteCellBefore: internal error: Could not extract parent-row of cell #{cell}")
|
2982
|
+
end
|
2983
|
+
row.elements.delete(previousCell)
|
2984
|
+
end
|
2985
|
+
end
|
2986
|
+
##########################################################################
|
2752
2987
|
# Inserts a new cell before the given cell thereby shifting existing cells
|
2753
2988
|
# cell=mySheet.getCell(5,1)
|
2754
2989
|
# mySheet.insertCellBefore(cell) # adds cell at beginning of row 5
|
2755
2990
|
#-------------------------------------------------------------------------
|
2756
2991
|
def insertCellBefore(cell)
|
2992
|
+
die("insertCellBefore: cell #{cell} is not a REXML::Element") unless (cell.class.to_s == "REXML::Element")
|
2757
2993
|
newCell=createCell(1)
|
2758
2994
|
cell.previous_sibling=newCell
|
2759
2995
|
#-----------------------------------------
|
@@ -2773,6 +3009,7 @@ class Rods
|
|
2773
3009
|
# mySheet.insertCellAfter(cell)
|
2774
3010
|
#-------------------------------------------------------------------------
|
2775
3011
|
def insertCellAfter(cell)
|
3012
|
+
die("insertCellAfter: cell #{cell} is not a REXML::Element") unless (cell.class.to_s == "REXML::Element")
|
2776
3013
|
newCell=createCell(1)
|
2777
3014
|
cell.next_sibling=newCell
|
2778
3015
|
#-----------------------------------------------------------------------
|
@@ -2795,6 +3032,46 @@ class Rods
|
|
2795
3032
|
return newCell
|
2796
3033
|
end
|
2797
3034
|
##########################################################################
|
3035
|
+
# Inserts and returns a cell at the given index in the given row,
|
3036
|
+
# thereby shifting existing cells.
|
3037
|
+
#
|
3038
|
+
# row=mySheet.getRow(5)
|
3039
|
+
# cell=mySheet.insertCellFromRow(row,17)
|
3040
|
+
#-------------------------------------------------------------------------
|
3041
|
+
def insertCellFromRow(row,colInd)
|
3042
|
+
die("insertCell: row #{row} is not a REXML::Element") unless (row.class.to_s == "REXML::Element")
|
3043
|
+
die("insertCell: index #{colInd} is not a Fixnum/Integer") unless (colInd.class.to_s == "Fixnum")
|
3044
|
+
die("insertCell: invalid index #{colInd}") unless (colInd > 0)
|
3045
|
+
tell("insertCell: inserting new cell in column:#{colInd}")
|
3046
|
+
cell=getCellFromRow(row,colInd)
|
3047
|
+
return insertCellBefore(cell)
|
3048
|
+
end
|
3049
|
+
##########################################################################
|
3050
|
+
# Inserts and returns a cell at the given index, thereby shifting existing cells.
|
3051
|
+
#
|
3052
|
+
# cell=mySheet.insertCell(4,17)
|
3053
|
+
#-------------------------------------------------------------------------
|
3054
|
+
def insertCell(rowInd,colInd)
|
3055
|
+
die("insertCell: index #{rowInd} is not a Fixnum/Integer") unless (rowInd.class.to_s == "Fixnum")
|
3056
|
+
die("insertCell: invalid index #{rowInd}") unless (rowInd > 0)
|
3057
|
+
die("insertCell: index #{colInd} is not a Fixnum/Integer") unless (colInd.class.to_s == "Fixnum")
|
3058
|
+
die("insertCell: invalid index #{colInd}") unless (colInd > 0)
|
3059
|
+
tell("insertCell: inserting new cell at #{rowInd}:#{colInd}")
|
3060
|
+
cell=getCell(rowInd,colInd)
|
3061
|
+
return insertCellBefore(cell)
|
3062
|
+
end
|
3063
|
+
##########################################################################
|
3064
|
+
# Inserts and returns a row at the given index, thereby shifting existing rows
|
3065
|
+
# row=mySheet.insertRow(1) # inserts row above former row 1
|
3066
|
+
#-------------------------------------------------------------------------
|
3067
|
+
def insertRow(rowInd)
|
3068
|
+
die("insertRow: invalid rowInd #{rowInd}") unless (rowInd > 0)
|
3069
|
+
die("insertRow: rowInd #{rowInd} is not a Fixnum/Integer") unless (rowInd.class.to_s == "Fixnum")
|
3070
|
+
tell("insertRow: inserting new row")
|
3071
|
+
row=getRow(rowInd)
|
3072
|
+
return insertRowAbove(row)
|
3073
|
+
end
|
3074
|
+
##########################################################################
|
2798
3075
|
# Inserts a new row above the given row thereby shifting existing rows
|
2799
3076
|
# row=mySheet.getRow(1)
|
2800
3077
|
# mySheet.insertRowAbove(row)
|
@@ -2823,31 +3100,70 @@ class Rods
|
|
2823
3100
|
return newRow
|
2824
3101
|
end
|
2825
3102
|
##########################################################################
|
3103
|
+
# Deletes the column at the given index
|
3104
|
+
#
|
3105
|
+
# mySheet.deleteColumn(8)
|
3106
|
+
#-------------------------------------------------------------------------
|
3107
|
+
def deleteColumn(colInd)
|
3108
|
+
die("deleteColumn: index #{colInd} is not a Fixnum/Integer") unless (colInd.class.to_s == "Fixnum")
|
3109
|
+
die("deleteColumn: invalid index #{colInd}") unless (colInd > 0)
|
3110
|
+
currentWidth=@tables[@currentTableName][WIDTH]
|
3111
|
+
die("deleteColumn: column-index #{colInd} is outside valid range/current table width") if (colInd > currentWidth)
|
3112
|
+
#-------------------------------------------------------------------
|
3113
|
+
# Entweder Wiederholungsattribut der fraglichen Spalte dekrementieren
|
3114
|
+
# oder selbige loeschen
|
3115
|
+
#-------------------------------------------------------------------
|
3116
|
+
currentTable=@tables[@currentTableName][NODE]
|
3117
|
+
column=getChildByIndex(currentTable,COLUMN,colInd)
|
3118
|
+
repetitions=column.attributes["table:number-columns-repeated"]
|
3119
|
+
if(repetitions && repetitions.to_i > 1)
|
3120
|
+
column.attributes["table:number-columns-repeated"]=(repetitions.to_i-1).to_s
|
3121
|
+
else
|
3122
|
+
table=column.elements["ancestor::table:table"]
|
3123
|
+
unless (table)
|
3124
|
+
die("deleteColumn: internal error: Could not extract parent-table of column #{column}")
|
3125
|
+
end
|
3126
|
+
table.elements.delete(column)
|
3127
|
+
end
|
3128
|
+
#-----------------------------------------------
|
3129
|
+
# Fuer alle existierenden Zeilen neue Zelle an
|
3130
|
+
# Spaltenposition einfuegen und dabei implizit
|
3131
|
+
# Tabellenbreite aktualisieren
|
3132
|
+
#-----------------------------------------------
|
3133
|
+
row=getRow(1)
|
3134
|
+
deleteCellFromRow(row,colInd)
|
3135
|
+
i=1
|
3136
|
+
while(row=getNextExistentRow(row)) # fuer alle Zeilen ab der zweiten
|
3137
|
+
deleteCellFromRow(row,colInd)
|
3138
|
+
i+=1
|
3139
|
+
end
|
3140
|
+
end
|
3141
|
+
##########################################################################
|
2826
3142
|
# Inserts a column at the given index, thereby shifting existing columns
|
2827
3143
|
# mySheet.insertColumn(1) # inserts column before former column 1
|
2828
3144
|
#-------------------------------------------------------------------------
|
2829
|
-
def insertColumn(
|
2830
|
-
die("insertColumn:
|
2831
|
-
die("insertColumn: index #{
|
3145
|
+
def insertColumn(colInd)
|
3146
|
+
die("insertColumn: index #{colInd} is not a Fixnum/Integer") unless (colInd.class.to_s == "Fixnum")
|
3147
|
+
die("insertColumn: invalid index #{colInd}") unless (colInd > 0)
|
2832
3148
|
tell("insertColumn: inserting new column")
|
2833
3149
|
currentTable=@tables[@currentTableName][NODE]
|
2834
3150
|
#-----------------------------------------------
|
2835
3151
|
# Neuer Spalteneintrag im Header mit impliziter
|
2836
3152
|
# Aktualisierung der Tabellenbreite
|
2837
3153
|
#-----------------------------------------------
|
2838
|
-
column=getChildByIndex(currentTable,COLUMN,
|
2839
|
-
|
3154
|
+
column=getChildByIndex(currentTable,COLUMN,colInd)
|
3155
|
+
insertColumnBeforeInHeader(column)
|
2840
3156
|
#-----------------------------------------------
|
2841
3157
|
# Fuer alle existierenden Zeilen neue Zelle an
|
2842
3158
|
# Spaltenposition einfuegen und dabei implizit
|
2843
3159
|
# Tabellenbreite aktualisieren
|
2844
3160
|
#-----------------------------------------------
|
2845
3161
|
row=getRow(1)
|
2846
|
-
cell=getChildByIndex(row,CELL,
|
3162
|
+
cell=getChildByIndex(row,CELL,colInd)
|
2847
3163
|
insertCellBefore(cell)
|
2848
3164
|
i=1
|
2849
3165
|
while(row=getNextExistentRow(row)) # fuer alle Zeilen ab der zweiten
|
2850
|
-
cell=getChildByIndex(row,CELL,
|
3166
|
+
cell=getChildByIndex(row,CELL,colInd)
|
2851
3167
|
insertCellBefore(cell)
|
2852
3168
|
i+=1
|
2853
3169
|
end
|
@@ -2856,12 +3172,12 @@ class Rods
|
|
2856
3172
|
# internal: returns cell at index if existent, nil otherwise
|
2857
3173
|
# row=getRowIfExists(4)
|
2858
3174
|
# if(row)
|
2859
|
-
# cell=
|
3175
|
+
# cell=getCellFromRowIfExists(row,7)
|
2860
3176
|
# unless(cell) .....
|
2861
3177
|
# end
|
2862
3178
|
#-------------------------------------------------------------------------
|
2863
|
-
def
|
2864
|
-
return getElementIfExists(row,CELL,
|
3179
|
+
def getCellFromRowIfExists(row,colInd)
|
3180
|
+
return getElementIfExists(row,CELL,colInd)
|
2865
3181
|
end
|
2866
3182
|
##########################################################################
|
2867
3183
|
# internal: returns row at index if existent, nil otherwise
|
@@ -2869,9 +3185,9 @@ class Rods
|
|
2869
3185
|
# ........
|
2870
3186
|
# end
|
2871
3187
|
#-------------------------------------------------------------------------
|
2872
|
-
def getRowIfExists(
|
3188
|
+
def getRowIfExists(rowInd)
|
2873
3189
|
currentTable=@tables[@currentTableName][NODE]
|
2874
|
-
return getElementIfExists(currentTable,ROW,
|
3190
|
+
return getElementIfExists(currentTable,ROW,rowInd)
|
2875
3191
|
end
|
2876
3192
|
##########################################################################
|
2877
3193
|
# internal: examines, whether element of given type (row, cell, column) and index
|
@@ -2949,14 +3265,17 @@ class Rods
|
|
2949
3265
|
:setStyle, :printOfficeStyles, :printAutoStyles, :getNextExistentRow, :getPreviousExistentRow,
|
2950
3266
|
:getNextExistentCell, :getPreviousExistentCell, :insertTableAfter, :insertTableBefore,
|
2951
3267
|
:writeComment, :save, :saveAs, :initialize, :writeText, :getCellsAndIndicesFor,
|
2952
|
-
:insertRowBelow, :insertRowAbove, :insertCellBefore, :insertCellAfter, :insertColumn
|
3268
|
+
:insertRowBelow, :insertRowAbove, :insertCellBefore, :insertCellAfter, :insertColumn,
|
3269
|
+
:insertRow, :insertCell, :insertCellFromRow, :deleteCellBefore, :deleteCellAfter,
|
3270
|
+
:deleteCell, :deleteCellFromRow, :deleteRowAbove, :deleteRowBelow, :deleteRow,
|
3271
|
+
:deleteColumn, :deleteRow2, :deleteCell2
|
2953
3272
|
|
2954
3273
|
private :tell, :die, :createCell, :createRow, :getChildByIndex, :createElement, :setRepetition, :initHousekeeping,
|
2955
3274
|
:getTableWidth, :padTables, :padRow, :time2TimeVal, :percent2PercentVal, :date2DateVal,
|
2956
|
-
:finalize, :init, :normalizeText, :getColor, :normStyleHash, :getStyle, :
|
2957
|
-
:getNumberOfSiblings, :
|
3275
|
+
:finalize, :init, :normalizeText, :getColor, :normStyleHash, :getStyle, :getIndex,
|
3276
|
+
:getNumberOfSiblings, :getIndexAndOrNumber, :createColumn,
|
2958
3277
|
:getAppropriateStyle, :checkStyleAttributes, :insertStyleAttributes, :cloneNode,
|
2959
3278
|
:writeStyle, :writeStyleXml, :style2Hash, :writeDefaultStyles, :writeXml,
|
2960
3279
|
:internalizeFormula, :getColorPalette, :open, :printStyles, :insertTableBeforeAfter,
|
2961
|
-
:
|
3280
|
+
:insertColumnBeforeInHeader, :getElementIfExists, :getRowIfExists, :getCellFromRowIfExists
|
2962
3281
|
end # Klassenende
|
data/rods.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{rods}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.9.0"
|
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"]
|
9
|
-
s.date = %q{2011-01-
|
9
|
+
s.date = %q{2011-01-17}
|
10
10
|
s.description = %q{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 ;-)}
|
11
11
|
s.email = %q{rods.ruby@online.de}
|
12
12
|
s.extra_rdoc_files = ["README", "lib/rods.rb"]
|
@@ -15,10 +15,11 @@ 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.3.7}
|
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
|
22
23
|
s.specification_version = 3
|
23
24
|
|
24
25
|
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: 59
|
5
|
+
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 9
|
9
|
+
- 0
|
10
|
+
version: 0.9.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Dr. Heinz Breinlinger
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-01-
|
18
|
+
date: 2011-01-17 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -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.3.7
|
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
|