rods 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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