rods 0.7.0 → 0.8.0

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.
Files changed (7) hide show
  1. data/Manifest +0 -1
  2. data/README +103 -45
  3. data/Rakefile +2 -2
  4. data/lib/rods.rb +213 -81
  5. data/rods.gemspec +5 -5
  6. metadata +5 -7
  7. data/lib/example.rb +0 -88
data/Manifest CHANGED
@@ -1,5 +1,4 @@
1
1
  Manifest
2
2
  README
3
3
  Rakefile
4
- lib/example.rb
5
4
  lib/rods.rb
data/README CHANGED
@@ -1,11 +1,13 @@
1
1
  = RODS - Ruby Open Document Spreadsheet
2
2
  This class provides a convenient interface for reading and writing
3
- spreadsheets conforming to Open Document Format v1.1. with Ruby 1.9.1 and 1.8.7..
3
+ spreadsheets conforming to Open Document Format v1.1.
4
4
  Installiation of an office-application (LibreOffice, OpenOffice.org) is not required as the code directly
5
- manipulates the XML-files in the zipped *.ods-container.
5
+ manipulates the XML-files in the zipped *.ods-container. The mere prerequisites are
6
+ gem install zip
7
+ gem install rods
6
8
 
7
9
  On my website http://ruby.homelinux.com/ruby/rods/ you can see the output of the script below.
8
- You can contact me at rodsdotrubyatonlinedotde (and drop me a line, if you like it ;-).
10
+ You can contact me at rods.ruby@online.de (and tell me about experiences, problems you encountered or drop me a line, if you like it ;-).
9
11
 
10
12
  link:images/Rods.jpg
11
13
 
@@ -14,6 +16,14 @@
14
16
  Licensed under the same terms as Ruby. No warranty is provided.
15
17
 
16
18
  = Changelog
19
+ * 0.8.0
20
+ * new function
21
+ * insertColumn
22
+ cf. Example 0.8.0 below
23
+ * 0.7.5
24
+ * new functions
25
+ * insertRowAbove, insertRowBelow, insertCellBefore, insertCellAfter
26
+ cf. Example 0.7.5 below
17
27
  * 0.7.0
18
28
  * added new function
19
29
  * getCellsAndIndicesFor(expression)
@@ -284,51 +294,54 @@
284
294
  puts("not so much: #{text} bucks") # -> "not so much: -7.78 bucks"
285
295
  end
286
296
  end
287
-
288
- = Example for additions in 0.6.1
289
297
 
290
- #!/usr/bin/ruby
291
- # coding: UTF-8
292
- #
293
- # Author: Dr. Heinz Breinlinger
294
- #
295
- require 'rubygems'
296
- require 'rods'
298
+ = Example 0.8.0
297
299
 
298
- mySheet=Rods.new("Template.ods")
299
- mySheet.insertTableAfter("Tabelle1","Neue Tabelle")
300
- mySheet.insertTableAfter("Neue Tabelle","Neue Tabelle2")
301
- mySheet.insertTableAfter("Neue Tabelle2","Neue Tabelle3")
302
- mySheet.insertTableAfter("Tabelle3","Neue Tabelle4")
303
- mySheet.insertTableBefore("Tabelle1","Vor1")
304
- mySheet.insertTableBefore("Neue Tabelle4","Vor4")
305
- mySheet.saveAs("Test2.ods")
306
- puts("done")
300
+ # #!/usr/bin/ruby
301
+ # # coding: UTF-8
302
+ # #
303
+ # # Author: Dr. Heinz Breinlinger
304
+ # #
305
+ # require 'rubygems'
306
+ # require 'rods'
307
+ #
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")
307
322
 
308
- = Example for additions in 0.6.2
323
+ = Example 0.7.5
309
324
 
310
- #!/usr/bin/ruby
311
- # coding: UTF-8
325
+ # #!/usr/bin/ruby
326
+ # # coding: UTF-8
327
+ # #
328
+ # # Author: Dr. Heinz Breinlinger
329
+ # #
330
+ # require 'rubygems'
331
+ # require 'rods'
312
332
  #
313
- # Author: Dr. Heinz Breinlinger
314
- #
315
- require 'rubygems'
316
- require 'rods'
317
-
318
- mySheet=Rods.new("Template.ods")
319
- cell=mySheet.writeGetCell(3,3,"string","Underline")
320
- mySheet.setAttributes(cell,{ "style:text-underline-color" => "blue",
321
- "style:text-underline-style" => "solid",
322
- "style:text-underline-width" => "auto"})
323
- cell=mySheet.writeGetCell(4,4,"string","Underline_Default_with_Black")
324
- #----------------------------------------------------------------------
325
- # if not specified otherwise, width and color are set to default
326
- # - black
327
- # - solid
328
- #----------------------------------------------------------------------
329
- mySheet.setAttributes(cell,{ "style:text-underline-style" => "solid" })
330
- mySheet.saveAs("Test3.ods")
331
- puts("done")
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")
332
345
 
333
346
  = Example 0.7.0
334
347
 
@@ -350,7 +363,7 @@
350
363
  # :row => rowIndex,
351
364
  # :col => colIndex}]
352
365
  #
353
- # Regular expressions for 'content' are alllowd but must be enclosed in
366
+ # Regular expressions for 'content' are allowed but must be enclosed in
354
367
  # single (not double) quotes !
355
368
  #
356
369
  # In case of no matches at all, an empty array is returned.
@@ -368,7 +381,7 @@
368
381
  # The following finds all occurences of a comma- or dot-separated number,
369
382
  # consisting of 1 digit before and 2 digits behind the decimal-separator.
370
383
  #-------------------------------------------------------------------------
371
- result=mySheet.getCellsAndIndicesFor('\d{1}[.,]\\d{2}')
384
+ result=mySheet.getCellsAndIndicesFor('\d{1}[.,]\d{2}')
372
385
  result.each{ |cellHash|
373
386
  puts("----------------------------------------------")
374
387
  puts("Node: #{cellHash[:cell]}") # Be aware: Prints out whole node ! ;-)
@@ -376,6 +389,51 @@
376
389
  puts("Column: #{cellHash[:col]}")
377
390
  }
378
391
  puts("done")
392
+
393
+ = Example for additions in 0.6.2
394
+
395
+ #!/usr/bin/ruby
396
+ # coding: UTF-8
397
+ #
398
+ # Author: Dr. Heinz Breinlinger
399
+ #
400
+ require 'rubygems'
401
+ require 'rods'
402
+
403
+ mySheet=Rods.new("Template.ods")
404
+ cell=mySheet.writeGetCell(3,3,"string","Underline")
405
+ mySheet.setAttributes(cell,{ "style:text-underline-color" => "blue",
406
+ "style:text-underline-style" => "solid",
407
+ "style:text-underline-width" => "auto"})
408
+ cell=mySheet.writeGetCell(4,4,"string","Underline_Default_with_Black")
409
+ #----------------------------------------------------------------------
410
+ # if not specified otherwise, width and color are set to default
411
+ # - black
412
+ # - solid
413
+ #----------------------------------------------------------------------
414
+ mySheet.setAttributes(cell,{ "style:text-underline-style" => "solid" })
415
+ mySheet.saveAs("Test3.ods")
416
+ puts("done")
417
+
418
+ = Example for additions in 0.6.1
419
+
420
+ #!/usr/bin/ruby
421
+ # coding: UTF-8
422
+ #
423
+ # Author: Dr. Heinz Breinlinger
424
+ #
425
+ require 'rubygems'
426
+ require 'rods'
427
+
428
+ mySheet=Rods.new("Template.ods")
429
+ mySheet.insertTableAfter("Tabelle1","Neue Tabelle")
430
+ mySheet.insertTableAfter("Neue Tabelle","Neue Tabelle2")
431
+ mySheet.insertTableAfter("Neue Tabelle2","Neue Tabelle3")
432
+ mySheet.insertTableAfter("Tabelle3","Neue Tabelle4")
433
+ mySheet.insertTableBefore("Tabelle1","Vor1")
434
+ mySheet.insertTableBefore("Neue Tabelle4","Vor4")
435
+ mySheet.saveAs("Test2.ods")
436
+ puts("done")
379
437
 
380
438
  = Caveat
381
439
 
data/Rakefile CHANGED
@@ -2,8 +2,8 @@ require 'rubygems'
2
2
  require 'rake'
3
3
  require 'echoe'
4
4
 
5
- Echoe.new('rods', '0.7.0') do |p|
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 rodsdotrubyatonlinedotde (and drop me a line, if you like it ;-)"
5
+ Echoe.new('rods', '0.8.0') do |p|
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/"
9
9
  p.author = "Dr. Heinz Breinlinger"
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # = RODS - Ruby Open Document Spreadsheet
4
4
  # This class provides a convenient interface for fast reading and writing
5
- # spreadsheets conforming to Open Document Format v1.1. with Ruby 1.9.1 and 1.8.7..
5
+ # spreadsheets conforming to Open Document Format v1.1..
6
6
  # Installiation of an office-application (LibreOffice, OpenOffice.org) is not required as the code directly
7
7
  # manipulates the XML-files in the zipped *.ods-container.
8
8
  #
@@ -14,57 +14,17 @@
14
14
  # As *.ods-files are zipped archives you need to
15
15
  # $ sudo gem install zip
16
16
  #
17
- # = What ist does
18
- # * open and save a spreadsheet
19
- # * save the spreadsheet under a different location/name
20
- # * add, delete and rename tables
21
- # * tables are always inserted at the end of the spreadsheet
22
- # * read cells with content of type
23
- # * string
24
- # * formula
25
- # * percent
26
- # * time
27
- # * date
28
- # * currency
29
- # * write cells with content of type
30
- # * string
31
- # * formula
32
- # * formula:float
33
- # * formula:date
34
- # * formula:time
35
- # * formula:currency
36
- # * percent
37
- # * time
38
- # * date
39
- # * 2 different date formats (German so far)
40
- # * currency
41
- # * German
42
- # * English
43
- # * insert annotations
44
- # * create styles and apply styles as well as features to cells
45
- # * style-name
46
- # * font-color
47
- # * background-color
48
- # * border
49
- # * all four sides or
50
- # * top,bottom,left,right
51
- # * indentation
52
- # * alignment
53
- # * font-weight ('bold')
54
- # * font-style ('italic')
55
- # * data-style-name (most important for language specific formattings)
56
- #
57
17
  # = Tutorial
58
- # Please refer to README for how to use the interface.
18
+ # Please refer to README for how to use the interface with many annotated examples.
59
19
  #
60
20
  require 'rubygems'
61
21
  require 'zip/zipfilesystem'
62
22
  require 'rexml/document'
63
23
 
64
-
65
24
  class Rods
66
25
  ROW="row"
67
26
  CELL="cell"
27
+ COLUMN="column"
68
28
  TAG="tag"
69
29
  TEXT="text"
70
30
  CHILD="child"
@@ -75,6 +35,8 @@ class Rods
75
35
  NODE="node"
76
36
  BEFORE="before"
77
37
  AFTER="after"
38
+ INDEX="index"
39
+ NUMBER="number"
78
40
  WIDTHEXCEEDED="exceeded"
79
41
  ##########################################################################
80
42
  # Convenience-function to switch the default-style for the display of
@@ -122,24 +84,48 @@ class Rods
122
84
  return createElement(ROW,repetition)
123
85
  end
124
86
  ##########################################################################
125
- # internal: Returns a new REXML::Element of type 'row' or 'cell' with repetition-attribute set to 'n'
87
+ # internal: Returns a new REXML::Element of type 'column' with repetition-attribute set to 'n'
88
+ #-------------------------------------------------------------------------
89
+ def createColumn(repetition)
90
+ return createElement(COLUMN,repetition)
91
+ end
92
+ ##########################################################################
93
+ # internal: Returns a new REXML::Element of type 'row', 'cell' or 'column'
94
+ # with repetition-attribute set to 'n'
126
95
  #-------------------------------------------------------------------------
127
96
  def createElement(type,repetition)
128
97
  if(repetition < 1)
129
98
  die("createElement: invalid value for repetition #{repetition}")
130
99
  end
100
+ #----------------------------------------------
101
+ # Zeile
102
+ #----------------------------------------------
131
103
  if(type == ROW)
132
104
  row=REXML::Element.new("table:table-row")
133
105
  if(repetition > 1)
134
106
  row.attributes["table:number-rows-repeated"]=repetition.to_s
135
107
  end
136
108
  return row
109
+ #----------------------------------------------
110
+ # Zelle
111
+ #----------------------------------------------
137
112
  elsif(type == CELL)
138
113
  cell=REXML::Element.new("table:table-cell")
139
114
  if(repetition > 1)
140
115
  cell.attributes["table:number-columns-repeated"]=repetition.to_s
141
116
  end
142
117
  return cell
118
+ #----------------------------------------------
119
+ # Spalte (als Tabellen-Header)
120
+ #----------------------------------------------
121
+ elsif(type == COLUMN)
122
+ column=REXML::Element.new("table:table-column")
123
+ if(repetition > 1)
124
+ column.attributes["table:number-columns-repeated"]=repetition.to_s
125
+ end
126
+ column.attributes["table:default-cell-style-name"]="Default"
127
+ return column
128
+ #----------------------------------------------
143
129
  else
144
130
  die("createElement: Invalid Type: #{type}")
145
131
  end
@@ -268,8 +254,8 @@ class Rods
268
254
  return getChildByIndex(currentTable,ROW,rowInd)
269
255
  end
270
256
  ##########################################################################
271
- # internal: returns the child REXML::Element of the given parent, type
272
- # ('row' or 'cell') and index within the parent-element.
257
+ # internal: returns the child REXML::Element of the given type
258
+ # ('row', 'cell' or 'column') and index within the parent-element.
273
259
  # The child is created if it does not exist.
274
260
  #------------------------------------------------------------------------
275
261
  def getChildByIndex(parent,type,index)
@@ -278,14 +264,14 @@ class Rods
278
264
  #----------------------------------------------------------------------
279
265
  # Validierung
280
266
  #----------------------------------------------------------------------
281
- if((type != ROW) && (type != CELL))
267
+ if((type != ROW) && (type != CELL) && (type != COLUMN))
282
268
  die("getChildByIndex: wrong type #{type}")
283
269
  end
284
270
  if(index < 1)
285
271
  die("getChildByIndex: invalid index #{index}")
286
272
  end
287
273
  if(! parent)
288
- die("getChildByIndex: parent-element is nil")
274
+ die("getChildByIndex: parent-element does not exist")
289
275
  end
290
276
  #----------------------------------------------------------------------
291
277
  # Typabhaengige Vorbelegungen
@@ -293,13 +279,21 @@ class Rods
293
279
  if(type == ROW)
294
280
  kindOfElement="table:table-row"
295
281
  kindOfRepetition="table:number-rows-repeated"
296
- elsif(type == CELL)
297
- kindOfElement="table:table-cell"
298
- kindOfRepetition="table:number-columns-repeated"
282
+ #---------------------------------------------------------------------
283
+ # in der "Horizontalen" (Zelle oder Spalte) ggf. Breitenwerte anpassen
284
+ # und typabhaengig vorbelegen
285
+ #---------------------------------------------------------------------
286
+ elsif((type == CELL) || (type == COLUMN))
299
287
  if(index > @tables[@currentTableName][WIDTH])
300
288
  @tables[@currentTableName][WIDTH]=index
301
289
  @tables[@currentTableName][WIDTHEXCEEDED]=true
302
290
  end
291
+ kindOfRepetition="table:number-columns-repeated"
292
+ case type
293
+ when CELL then kindOfElement="table:table-cell"
294
+ when COLUMN then kindOfElement="table:table-column"
295
+ else die("getChildByIndex: internal error: when-clause-failure for type #{type}")
296
+ end
303
297
  else
304
298
  die("getChildByIndex: wrong type #{type}")
305
299
  end
@@ -486,11 +480,11 @@ class Rods
486
480
  insertTableBeforeAfter(relativeTableName,tableName,AFTER)
487
481
  end
488
482
  ##########################################################################
489
- # Internal: Inserts a table of the given name before or after the given spreadsheet and updates
490
- # the internal table-administration.
483
+ # internal: Inserts a table of the given name before or after the given spreadsheet and updates
484
+ # the internal table-administration. The default position is 'after'.
491
485
  # mySheet.insertTableBeforeAfter("table1","table2",BEFORE)
492
486
  #-------------------------------------------------------------------------
493
- def insertTableBeforeAfter(relativeTableName,tableName,position="after")
487
+ def insertTableBeforeAfter(relativeTableName,tableName,position=AFTER)
494
488
  die("insertTableAfter: table '#{relativeTableName}' does not exist") unless (@tables.has_key?(relativeTableName))
495
489
  die("insertTableAfter: table '#{tableName}' already exists") if (@tables.has_key?(tableName))
496
490
  #-----------------------------------------
@@ -603,7 +597,7 @@ class Rods
603
597
  numColumnsOfTable+=1
604
598
  numRepetitions=tableColumn.attributes["table:number-columns-repeated"]
605
599
  if(numRepetitions)
606
- numColumnsOfTable+=numRepetitions.to_i
600
+ numColumnsOfTable+=numRepetitions.to_i-1
607
601
  end
608
602
  }
609
603
  tell("getTableWidth: width of '#{tableName}': #{numColumnsOfTable}")
@@ -614,7 +608,7 @@ class Rods
614
608
  # according to the right-most valid column. This routine is called when
615
609
  # the spreadsheet is saved.
616
610
  #------------------------------------------------------------------------
617
- def padTable
611
+ def padTables
618
612
  #---------------------------------------------------------------
619
613
  # Ggf. geaenderte Tabellenbreite setzen und
620
614
  # alle Zeilen auf neue Tabellenbreite auffuellen
@@ -624,7 +618,7 @@ class Rods
624
618
  width=tableHash[WIDTH]
625
619
  numColumnsOfTable=getTableWidth(table)
626
620
  if(tableHash[WIDTHEXCEEDED])
627
- die("padTable: current table does not contain table:table-column") unless(table.elements["table:table-column"])
621
+ die("padTables: current table does not contain table:table-column") unless(table.elements["table:table-column"])
628
622
  #--------------------------------------------------------------
629
623
  # Differenz zu Sollbreite ermitteln und Wiederholungszahl des
630
624
  # letzten Spalteneintrages aktualisieren/setzen
@@ -633,19 +627,19 @@ class Rods
633
627
  if(lastTableColumn.attributes["table:number-columns-repeated"])
634
628
  numRepetitions=(lastTableColumn.attributes["table:number-columns-repeated"]).to_i+width-numColumnsOfTable
635
629
  else
636
- numRepetitions=width-numColumnsOfTable
630
+ numRepetitions=width-numColumnsOfTable+1 # '+1' da Spalte selbst als Wiederholung zaehlt !
637
631
  end
638
632
  lastTableColumn.attributes["table:number-columns-repeated"]=numRepetitions.to_s
639
633
  tableHash[WIDTHEXCEEDED]=false
640
- tell("padTable: adjusted columns: #{numColumnsOfTable} -> #{width}")
634
+ tell("padTables: adjusted columns: #{numColumnsOfTable} -> #{width}")
641
635
  else
642
- tell("padTable: equal: #{numColumnsOfTable} <-> #{width}")
636
+ tell("padTables: equal: #{numColumnsOfTable} <-> #{width}")
643
637
  end
644
638
  }
645
639
  end
646
640
  ##########################################################################
647
641
  # internal: This routine pads the given row with newly created cells and/or
648
- # adapts their repetition-attributes. It was formerly called by 'padTable' and is obsolete.
642
+ # adapts their repetition-attributes. It was formerly called by 'padTables' and is obsolete.
649
643
  #----------------------------------------------------------------------
650
644
  def padRow(row,width)
651
645
  j=0
@@ -951,7 +945,7 @@ class Rods
951
945
  #------------------------
952
946
  # content.xml
953
947
  #------------------------
954
- padTable()
948
+ padTables()
955
949
  tell("finalize: writing content.xml ...")
956
950
  zipfile.file.open("content.xml","w") { |outfile|
957
951
  outfile.puts @contentText.to_s
@@ -2513,7 +2507,7 @@ class Rods
2513
2507
  "palegreen" => "#ccffff",
2514
2508
  "darkpurple" => "#660066",
2515
2509
  "salmon" => "#ff8080"
2516
- }
2510
+ }
2517
2511
  @fixedStyles=["myTable", "myRow", "myColumn", "myFloatFormat", "myFloat", "myTimeFormat",
2518
2512
  "myTime", "myPercentFormat", "myPercent", "myString", "myDateFormat",
2519
2513
  "myDate", "myDateFormatDay", "myDateDay", "myCurrencyFormatPositive",
@@ -2555,7 +2549,7 @@ class Rods
2555
2549
  ##########################################################################
2556
2550
  # Fast Routine to get the next cell, because XML-Parser does not have
2557
2551
  # to start from top-node of row to find cell !
2558
- # Returns next cell as a REXML::Element or nil if no element exists
2552
+ # Returns next cell as a REXML::Element or nil if no element exists.
2559
2553
  # Cf. explanation in README !
2560
2554
  #------------------------------------------------------------------------
2561
2555
  def getNextExistentCell(cell)
@@ -2564,7 +2558,7 @@ class Rods
2564
2558
  ##########################################################################
2565
2559
  # Fast Routine to get the previous cell, because XML-Parser does not have
2566
2560
  # to start from top-node of row to find cell !
2567
- # Returns previous cell as a REXML::Element or nil if no element exists
2561
+ # Returns previous cell as a REXML::Element or nil if no element exists.
2568
2562
  # Cf. explanation in README !
2569
2563
  #------------------------------------------------------------------------
2570
2564
  def getPreviousExistentCell(cell)
@@ -2573,7 +2567,7 @@ class Rods
2573
2567
  ##########################################################################
2574
2568
  # Fast Routine to get the next row, because XML-Parser does not have
2575
2569
  # to start from top-node of document to find row !
2576
- # Returns next row as a REXML::Element or nil if no element exists
2570
+ # Returns next row as a REXML::Element or nil if no element exists.
2577
2571
  # Cf. explanation in README !
2578
2572
  #------------------------------------------------------------------------
2579
2573
  def getNextExistentRow(row)
@@ -2589,7 +2583,7 @@ class Rods
2589
2583
  # :row => rowIndex,
2590
2584
  # :col => colIndex}]
2591
2585
  #
2592
- # Regular expressions for 'content' are alllowd but must be enclosed in
2586
+ # Regular expressions for 'content' are allowed but must be enclosed in
2593
2587
  # single (not double) quotes !
2594
2588
  #
2595
2589
  # In case of no matches at all, an empty array is returned.
@@ -2657,15 +2651,33 @@ class Rods
2657
2651
  return result
2658
2652
  end
2659
2653
  ##########################################################################
2654
+ # internal: Wrapper for
2655
+ # getIndexOrNumberOfSiblings(node,NUMBER)
2656
+ #-------------------------------------------------------------------------
2657
+ def getNumberOfSiblings(node)
2658
+ return getIndexOrNumberOfSiblings(node,NUMBER)
2659
+ end
2660
+ ##########################################################################
2661
+ # internal: Wrapper for
2662
+ # getIndexOrNumberOfSiblings(node,INDEX)
2663
+ #-------------------------------------------------------------------------
2664
+ def getIndexOfElement(node)
2665
+ return getIndexOrNumberOfSiblings(node,INDEX)
2666
+ end
2667
+ ##########################################################################
2660
2668
  # internal: Calculates index (in the sense of spreadsheet, NOT XML) of
2661
- # given element (row or cell as REXML::Element) within the corresponding parent-element
2662
- # (table or row)
2669
+ # given element (row, cell or column as REXML::Element) within the
2670
+ # corresponding parent-element (table or row) or the number of siblings
2671
+ # of the same kind - depending on given flag
2663
2672
  #
2664
- # index=mySheet.getIndexOfElement(row) # -> Line-number within table
2673
+ # index=mySheet.getIndexOrNumberOfElements(row,INDEX) # -> Line-number within table
2674
+ # numColumns=mySheet.getIndexOrNumberOfElements(column,NUMBER) # number of columns
2665
2675
  #-------------------------------------------------------------------------
2666
- def getIndexOfElement(node)
2667
- die("getIndexOfElements: passed node '#{node}' is not a REXML::Element") unless (node.class.to_s == "REXML::Element")
2668
- index=0
2676
+ def getIndexOrNumberOfSiblings(node,flag)
2677
+ die("getIndexOrNumberOfSiblings: passed node '#{node}' is not a REXML::Element") \
2678
+ unless (node.class.to_s == "REXML::Element")
2679
+ die("getIndexOrNumberOfSiblings: internal error: invalid flag '#{flag}'") \
2680
+ unless (flag == NUMBER || flag == INDEX)
2669
2681
  #--------------------------------------------------------------
2670
2682
  # Typabhaengige Vorbelegungen
2671
2683
  #--------------------------------------------------------------
@@ -2673,29 +2685,37 @@ class Rods
2673
2685
  kindOfSelf="table:table-cell"
2674
2686
  kindOfParent="table:table-row"
2675
2687
  kindOfRepetition="table:number-columns-repeated"
2688
+ elsif(node.elements["self::table:table-column"])
2689
+ kindOfSelf="table:table-column"
2690
+ kindOfParent="table:table"
2691
+ kindOfRepetition="table:number-columns-repeated"
2676
2692
  elsif(node.elements["self::table:table-row"])
2677
2693
  kindOfSelf="table:table-row"
2678
2694
  kindOfParent="table:table"
2679
2695
  kindOfRepetition="table:number-rows-repeated"
2680
2696
  else
2681
- die("getIndexOfElement: internal error: passed element '#{node}' is neither cell nor row")
2697
+ die("getIndexOrNumberOfSiblings: internal error: passed element '#{node}' is neither cell, nor row or column")
2682
2698
  end
2683
2699
  #--------------------------------------------------------------
2684
2700
  # Zugehoeriges Vater-Element ermitteln
2685
2701
  #--------------------------------------------------------------
2686
2702
  parent=node.elements["ancestor::"+kindOfParent]
2687
2703
  unless (parent)
2688
- die("getIndexOfElement: internal error: Could not extract parent of #{node}")
2704
+ die("getIndexOrNumberOfSiblings: internal error: Could not extract parent of #{node}")
2689
2705
  end
2690
2706
  #--------------------------------------------------------------
2691
- # Index des Kind-Elements innerhalb Vater-Element ermitteln
2707
+ # Index des Kind-Elements innerhalb Vater-Element oder
2708
+ # Gesamtzahl der Siblings ermitteln
2692
2709
  #--------------------------------------------------------------
2710
+ index=0
2693
2711
  parent.elements.each(kindOfSelf){ |child|
2694
2712
  index+=1
2695
2713
  #-----------------------------------------------
2696
2714
  # Bei Treffer -> Ruecksprung mit aktuellem Index
2715
+ # sofern Indizierungsflag gesetzt, sonst
2716
+ # verwerfen und weiterzaehlen
2697
2717
  #-----------------------------------------------
2698
- if(child == node)
2718
+ if(flag == INDEX && child == node)
2699
2719
  return index
2700
2720
  #-----------------------------------------------
2701
2721
  # Wiederholungen zaehlen
@@ -2706,7 +2726,116 @@ class Rods
2706
2726
  index+=repetition.to_i-1
2707
2727
  end
2708
2728
  }
2709
- die("getIndexOfElement: internal error: Could not calculate index of element #{node}")
2729
+ if(flag == INDEX)
2730
+ die("getIndexOrNumberOfSiblings: internal error: Could not calculate index of element #{node}")
2731
+ else
2732
+ return index # <- hier: Letzter Index == Gesamtzahl der Siblings
2733
+ end
2734
+ end
2735
+ ##########################################################################
2736
+ # internal: Inserts a new header-column before the given column thereby
2737
+ # shifting existing column-header-entries
2738
+ #-------------------------------------------------------------------------
2739
+ def insertColumnBefore(column)
2740
+ newColumn=createColumn(1)
2741
+ column.previous_sibling=newColumn
2742
+ #-----------------------------------------
2743
+ # bisherige Tabellenbreite überschritten ?
2744
+ #-----------------------------------------
2745
+ lengthOfHeader=getNumberOfSiblings(column)
2746
+ if(lengthOfHeader > @tables[@currentTableName][WIDTH])
2747
+ @tables[@currentTableName][WIDTH]=lengthOfHeader
2748
+ @tables[@currentTableName][WIDTHEXCEEDED]=true
2749
+ end
2750
+ return newColumn
2751
+ end
2752
+ ##########################################################################
2753
+ # Inserts a new cell before the given cell thereby shifting existing cells
2754
+ # cell=mySheet.getCell(5,1)
2755
+ # mySheet.insertCellBefore(cell) # adds cell at beginning of row 5
2756
+ #-------------------------------------------------------------------------
2757
+ def insertCellBefore(cell)
2758
+ newCell=createCell(1)
2759
+ cell.previous_sibling=newCell
2760
+ #-----------------------------------------
2761
+ # bisherige Tabellenbreite überschritten ?
2762
+ #-----------------------------------------
2763
+ lengthOfRow=getNumberOfSiblings(cell)
2764
+ if(lengthOfRow > @tables[@currentTableName][WIDTH])
2765
+ @tables[@currentTableName][WIDTH]=lengthOfRow
2766
+ @tables[@currentTableName][WIDTHEXCEEDED]=true
2767
+ tell("insertCellBefore: new table width: #{lengthOfRow}")
2768
+ end
2769
+ return newCell
2770
+ end
2771
+ ##########################################################################
2772
+ # Inserts a new cell after the given cell thereby shifting existing cells
2773
+ # cell=mySheet.getCell(4,7)
2774
+ # mySheet.insertCellAfter(cell)
2775
+ #-------------------------------------------------------------------------
2776
+ def insertCellAfter(cell)
2777
+ newCell=createCell(1)
2778
+ cell.next_sibling=newCell
2779
+ #-----------------------------------------
2780
+ # bisherige Tabellenbreite überschritten ?
2781
+ #-----------------------------------------
2782
+ lengthOfRow=getNumberOfSiblings(cell)
2783
+ if(lengthOfRow > @tables[@currentTableName][WIDTH])
2784
+ @tables[@currentTableName][WIDTH]=lengthOfRow
2785
+ @tables[@currentTableName][WIDTHEXCEEDED]=true
2786
+ tell("insertCellAfter: new table width: #{lengthOfRow}")
2787
+ end
2788
+ return newCell
2789
+ end
2790
+ ##########################################################################
2791
+ # Inserts a new row above the given row thereby shifting existing rows
2792
+ # row=mySheet.getRow(1)
2793
+ # mySheet.insertRowAbove(row)
2794
+ #-------------------------------------------------------------------------
2795
+ def insertRowAbove(row)
2796
+ newRow=createRow(1)
2797
+ row.previous_sibling=newRow
2798
+ return newRow
2799
+ end
2800
+ ##########################################################################
2801
+ # Inserts a new row below the given row thereby shifting existing rows
2802
+ # row=mySheet.getRow(8)
2803
+ # mySheet.insertRowBelow(row)
2804
+ #-------------------------------------------------------------------------
2805
+ def insertRowBelow(row)
2806
+ newRow=createRow(1)
2807
+ row.next_sibling=newRow
2808
+ return newRow
2809
+ end
2810
+ ##########################################################################
2811
+ # Inserts a column at the given index, thereby shifting existing columns
2812
+ # mySheet.insertColumn(1) # inserts column before former column 1
2813
+ #-------------------------------------------------------------------------
2814
+ def insertColumn(index)
2815
+ die("insertColumn: invalid index #{index}") unless (index > 0)
2816
+ die("insertColumn: index #{index} is not a Fixnum/Integer") unless (index.class.to_s == "Fixnum")
2817
+ tell("insertColumn: inserting new column")
2818
+ currentTable=@tables[@currentTableName][NODE]
2819
+ #-----------------------------------------------
2820
+ # Neuer Spalteneintrag im Header mit impliziter
2821
+ # Aktualisierung der Tabellenbreite
2822
+ #-----------------------------------------------
2823
+ column=getChildByIndex(currentTable,COLUMN,index)
2824
+ insertColumnBefore(column)
2825
+ #-----------------------------------------------
2826
+ # Fuer alle existierenden Zeilen neue Zelle an
2827
+ # Spaltenposition einfuegen und dabei implizit
2828
+ # Tabellenbreite aktualisieren
2829
+ #-----------------------------------------------
2830
+ row=getRow(1)
2831
+ cell=getChildByIndex(row,CELL,index)
2832
+ insertCellBefore(cell)
2833
+ i=1
2834
+ while(row=getNextExistentRow(row)) # fuer alle Zeilen ab der zweiten
2835
+ cell=getChildByIndex(row,CELL,index)
2836
+ insertCellBefore(cell)
2837
+ i+=1
2838
+ end
2710
2839
  end
2711
2840
  ##########################################################################
2712
2841
  # internal: Opens zip-file
@@ -2729,12 +2858,15 @@ class Rods
2729
2858
  :insertTable, :deleteTable, :readCellFromRow, :readCell, :setAttributes, :writeStyleAbbr,
2730
2859
  :setStyle, :printOfficeStyles, :printAutoStyles, :getNextExistentRow, :getPreviousExistentRow,
2731
2860
  :getNextExistentCell, :getPreviousExistentCell, :insertTableAfter, :insertTableBefore,
2732
- :writeComment, :save, :saveAs, :initialize, :writeText, :getCellsAndIndicesFor
2861
+ :writeComment, :save, :saveAs, :initialize, :writeText, :getCellsAndIndicesFor,
2862
+ :insertRowBelow, :insertRowAbove, :insertCellBefore, :insertCellAfter, :insertColumn
2733
2863
 
2734
2864
  private :tell, :die, :createCell, :createRow, :getChildByIndex, :createElement, :setRepetition, :initHousekeeping,
2735
- :getTableWidth, :padTable, :padRow, :time2TimeVal, :percent2PercentVal, :date2DateVal,
2865
+ :getTableWidth, :padTables, :padRow, :time2TimeVal, :percent2PercentVal, :date2DateVal,
2736
2866
  :finalize, :init, :normalizeText, :getColor, :normStyleHash, :getStyle, :getIndexOfElement,
2867
+ :getNumberOfSiblings, :getIndexOrNumberOfSiblings, :createColumn,
2737
2868
  :getAppropriateStyle, :checkStyleAttributes, :insertStyleAttributes, :cloneNode,
2738
2869
  :writeStyle, :writeStyleXml, :style2Hash, :writeDefaultStyles, :writeXml,
2739
- :internalizeFormula, :getColorPalette, :open, :printStyles, :insertTableBeforeAfter
2870
+ :internalizeFormula, :getColorPalette, :open, :printStyles, :insertTableBeforeAfter,
2871
+ :insertColumnBefore
2740
2872
  end # Klassenende
@@ -2,15 +2,15 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{rods}
5
- s.version = "0.7.0"
5
+ s.version = "0.8.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-11}
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 rodsdotrubyatonlinedotde (and drop me a line, if you like it ;-)}
9
+ s.date = %q{2011-01-13}
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
- s.extra_rdoc_files = ["README", "lib/example.rb", "lib/rods.rb"]
13
- s.files = ["Manifest", "README", "Rakefile", "lib/example.rb", "lib/rods.rb", "rods.gemspec"]
12
+ s.extra_rdoc_files = ["README", "lib/rods.rb"]
13
+ s.files = ["Manifest", "README", "Rakefile", "lib/rods.rb", "rods.gemspec"]
14
14
  s.homepage = %q{http://ruby.homelinux.com/ruby/rods/}
15
15
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Rods", "--main", "README"]
16
16
  s.require_paths = ["lib"]
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: 3
4
+ hash: 63
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 7
8
+ - 8
9
9
  - 0
10
- version: 0.7.0
10
+ version: 0.8.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Dr. Heinz Breinlinger
@@ -15,11 +15,11 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-01-11 00:00:00 +01:00
18
+ date: 2011-01-13 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
22
- 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 rodsdotrubyatonlinedotde (and drop me a line, if you like it ;-)"
22
+ 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 ;-)"
23
23
  email: rods.ruby@online.de
24
24
  executables: []
25
25
 
@@ -27,13 +27,11 @@ extensions: []
27
27
 
28
28
  extra_rdoc_files:
29
29
  - README
30
- - lib/example.rb
31
30
  - lib/rods.rb
32
31
  files:
33
32
  - Manifest
34
33
  - README
35
34
  - Rakefile
36
- - lib/example.rb
37
35
  - lib/rods.rb
38
36
  - rods.gemspec
39
37
  has_rdoc: true
@@ -1,88 +0,0 @@
1
- # coding: UTF-8
2
- require 'rubygems'
3
- require 'rods'
4
- mySheet=Rods.new("/home/heinz/Work/Template.ods",["de","DE","€","EUR"])
5
- # aternative values for United States would be
6
- # mySheet=Rods.new("/home/heinz/Work/Template.ods",["us","US","$","DOLLAR"])
7
- mySheet.renameTable("Tabelle1","not needed")
8
- mySheet.insertTable("example")
9
- mySheet.setCurrentTable("example")
10
- mySheet.deleteTable("Tabelle2")
11
- mySheet.deleteTable("Tabelle3")
12
- mySheet.writeCell(1,1,"date","31.12.2010")
13
- mySheet.writeCell(2,1,"formula:date","=A1+1")
14
- mySheet.setDateFormat("myDateDay")
15
- mySheet.writeCell(1,2,"formula:date","=A1")
16
- mySheet.writeCell(2,2,"formula:date","=A2")
17
- mySheet.setDateFormat("myDate")
18
- mySheet.writeCell(1,3,"time","13:37")
19
- mySheet.writeCell(2,3,"time","20:15")
20
- mySheet.writeCell(1,4,"currency","19,99")
21
- mySheet.writeCell(2,4,"currency","-7,78")
22
- cell=mySheet.writeGetCell(3,3,"formula:time","=C2-C1")
23
- mySheet.setAttributes(cell,{ "border" => "0.01cm solid turquoise",
24
- "text-align" => "center",
25
- "background-color" => "yellow2",
26
- "color" => "blue"})
27
- cell=mySheet.writeGetCell(3,4,"formula:currency","=D2+D1")
28
- mySheet.setAttributes(cell,{ "border-right" => "0.05cm solid magenta4",
29
- "border-bottom" => "0.03cm solid lightgreen",
30
- "border-top" => "0.08cm solid salmon",
31
- "font-style" => "italic",
32
- "font-weight" => "bold"})
33
- mySheet.writeStyleAbbr({"name" => "myNewPercentStyle",
34
- "margin-left" => "0.3cm",
35
- "text-align" => "start",
36
- "color" => "blue",
37
- "border" => "0.01cm solid black",
38
- "font-style" => "italic",
39
- "data-style-name" => "myPercentFormat",
40
- "font-weight" => "bold"})
41
- cell=mySheet.writeGetCell(4,2,"percent","4,71")
42
- mySheet.setStyle(cell,"myNewPercentStyle")
43
- mySheet.writeComment(cell,"by Dr. Heinz Breinlinger")
44
- cell=mySheet.writeGetCell(4,3,"formula:time","=B4*C3")
45
- mySheet.setAttributes(cell,{ "color" => "lightmagenta",
46
- "font-style" => "italic"})
47
- cell=mySheet.writeGetCell(4,4,"formula:currency","=B4*D3")
48
- mySheet.setAttributes(cell,{ "color" => "turquoise7",
49
- "text-align" => "center",
50
- "font-style" => "bold"})
51
- mySheet.writeStyleAbbr({"name" => "myBold",
52
- "text-align" => "end",
53
- "font-weight" => "bold",
54
- "background-color" => "purple"})
55
- cell=mySheet.writeGetCell(3,1,"string","Diff/Sum")
56
- mySheet.setStyle(cell,"myBold")
57
- cell=mySheet.writeGetCell(4,1,"string","Percent")
58
- mySheet.setStyle(cell,"myBold")
59
- cell=mySheet.writeGetCell(6,1,"string","annotation")
60
- mySheet.writeComment(cell,"C3,C4,D3,D4 are formulas")
61
- 1.upto(7){ |row|
62
- cell=mySheet.getCell(row,5)
63
- mySheet.setAttributes(cell,{ "border-right" => "0.07cm solid green6" })
64
- }
65
- 1.upto(5){ |col|
66
- cell=mySheet.getCell(7,col)
67
- mySheet.setAttributes(cell,{ "border-bottom" => "0.085cm solid red5" }) #
68
- }
69
- amount=0.0
70
- 1.upto(2){ |i|
71
- row=mySheet.getRow(i)
72
- text,type=mySheet.readCellFromRow(row,4)
73
- if(type == "currency")
74
- amount+=text.to_f
75
- end
76
- }
77
- mySheet.deleteTable("not needed")
78
- mySheet.saveAs("/home/heinz/Work/Example.ods")
79
- puts("Sums up to: #{amount}") # -> "Sums up to: 12.21"
80
- #----------Open Example.ods again---------------------------
81
- mySheet=Rods.new("/home/heinz/Work/Example.ods")
82
- mySheet.setCurrentTable("example") # not essential, as 'example' is the 1st and only table
83
- text,type=mySheet.readCell(2,4)
84
- if(text && type)
85
- if(type == "currency")
86
- puts("not so much: #{text} bucks") # -> "not so much: -7.78 bucks"
87
- end
88
- end