rubyXL 2.2.0 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/rubyXL/objects/border.rb +3 -3
- data/lib/rubyXL/objects/chartsheet.rb +20 -5
- data/lib/rubyXL/objects/fill.rb +3 -3
- data/lib/rubyXL/objects/filters.rb +5 -5
- data/lib/rubyXL/objects/font.rb +3 -3
- data/lib/rubyXL/objects/ooxml_object.rb +209 -138
- data/lib/rubyXL/objects/relationships.rb +2 -2
- data/lib/rubyXL/objects/sheet_common.rb +2 -2
- data/lib/rubyXL/objects/stylesheet.rb +35 -35
- data/lib/rubyXL/objects/workbook.rb +26 -27
- data/lib/rubyXL/objects/worksheet.rb +59 -51
- data/lib/rubyXL/parser.rb +22 -12
- data/lib/rubyXL/workbook.rb +5 -6
- data/lib/rubyXL/worksheet.rb +3 -3
- data/lib/rubyXL/writer/workbook_writer.rb +2 -2
- data/rdoc/README_rdoc.html +1 -1
- data/rdoc/RubyXL.html +1 -1
- data/rdoc/RubyXL/AExtensionStorageArea.html +1 -1
- data/rdoc/RubyXL/Alignment.html +1 -1
- data/rdoc/RubyXL/AlternateContent.html +1 -1
- data/rdoc/RubyXL/AutoFilter.html +1 -1
- data/rdoc/RubyXL/AutoFilterColumn.html +1 -1
- data/rdoc/RubyXL/BooleanNode.html +1 -1
- data/rdoc/RubyXL/BooleanValue.html +1 -1
- data/rdoc/RubyXL/Border.html +1 -1
- data/rdoc/RubyXL/BorderEdge.html +1 -1
- data/rdoc/RubyXL/{FillContainer.html → Borders.html} +5 -5
- data/rdoc/RubyXL/Break.html +1 -1
- data/rdoc/RubyXL/BreakList.html +2 -2
- data/rdoc/RubyXL/CalculationChain.html +1 -1
- data/rdoc/RubyXL/CalculationChainCell.html +1 -1
- data/rdoc/RubyXL/CalculationProperties.html +1 -1
- data/rdoc/RubyXL/Cell.html +1 -1
- data/rdoc/RubyXL/CellSmartTag.html +1 -1
- data/rdoc/RubyXL/CellSmartTagProperty.html +1 -1
- data/rdoc/RubyXL/CellSmartTags.html +105 -0
- data/rdoc/RubyXL/CellStyle.html +1 -1
- data/rdoc/RubyXL/CellStyleXFs.html +105 -0
- data/rdoc/RubyXL/CellStyles.html +105 -0
- data/rdoc/RubyXL/CellValue.html +1 -1
- data/rdoc/RubyXL/CellWatch.html +1 -1
- data/rdoc/RubyXL/{CellXFContainer.html → CellWatches.html} +5 -5
- data/rdoc/RubyXL/CellXFs.html +105 -0
- data/rdoc/RubyXL/Chartsheet.html +1 -1
- data/rdoc/RubyXL/ChartsheetPageSetup.html +1 -1
- data/rdoc/RubyXL/ChartsheetProperties.html +1 -1
- data/rdoc/RubyXL/ChartsheetProtection.html +1 -1
- data/rdoc/RubyXL/ChartsheetView.html +1 -1
- data/rdoc/RubyXL/{BorderContainer.html → ChartsheetViews.html} +4 -4
- data/rdoc/RubyXL/Color.html +1 -1
- data/rdoc/RubyXL/ColorFilter.html +1 -1
- data/rdoc/RubyXL/ColorScale.html +1 -1
- data/rdoc/RubyXL/ColorScheme.html +1 -1
- data/rdoc/RubyXL/ColorSet.html +1 -1
- data/rdoc/RubyXL/Colors.html +1 -1
- data/rdoc/RubyXL/ColumnRange.html +1 -1
- data/rdoc/RubyXL/ColumnRanges.html +1 -1
- data/rdoc/RubyXL/ConditionalFormatValue.html +1 -1
- data/rdoc/RubyXL/ConditionalFormatting.html +2 -2
- data/rdoc/RubyXL/ConditionalFormattingRule.html +1 -1
- data/rdoc/RubyXL/CustomFilter.html +1 -1
- data/rdoc/RubyXL/{CustomFilterContainer.html → CustomFilters.html} +5 -5
- data/rdoc/RubyXL/{CellStyleXFContainer.html → CustomProperties.html} +5 -5
- data/rdoc/RubyXL/CustomProperty.html +1 -1
- data/rdoc/RubyXL/CustomSheetView.html +1 -1
- data/rdoc/RubyXL/CustomSheetViews.html +2 -2
- data/rdoc/RubyXL/CustomWorkbookView.html +1 -1
- data/rdoc/RubyXL/{CustomWorkbookViewContainer.html → CustomWorkbookViews.html} +5 -5
- data/rdoc/RubyXL/DXF.html +1 -1
- data/rdoc/RubyXL/DXFs.html +1 -1
- data/rdoc/RubyXL/DataBar.html +1 -1
- data/rdoc/RubyXL/DataConsolidate.html +1 -1
- data/rdoc/RubyXL/DataConsolidationReference.html +1 -1
- data/rdoc/RubyXL/DataConsolidationReferences.html +2 -2
- data/rdoc/RubyXL/DataValidation.html +1 -1
- data/rdoc/RubyXL/DataValidations.html +1 -1
- data/rdoc/RubyXL/DateGroupItem.html +1 -1
- data/rdoc/RubyXL/DefinedName.html +1 -1
- data/rdoc/RubyXL/DefinedNames.html +2 -2
- data/rdoc/RubyXL/DocumentProperties.html +1 -1
- data/rdoc/RubyXL/DynamicFilter.html +1 -1
- data/rdoc/RubyXL/EmbeddedControl.html +1 -1
- data/rdoc/RubyXL/{EmbeddedControlContainer.html → EmbeddedControls.html} +5 -5
- data/rdoc/RubyXL/Extension.html +1 -1
- data/rdoc/RubyXL/ExtensionStorageArea.html +1 -1
- data/rdoc/RubyXL/ExternalReference.html +1 -1
- data/rdoc/RubyXL/ExternalReferences.html +2 -2
- data/rdoc/RubyXL/FieldItem.html +1 -1
- data/rdoc/RubyXL/FileRecoveryProperties.html +1 -1
- data/rdoc/RubyXL/FileSharing.html +1 -1
- data/rdoc/RubyXL/FileVersion.html +1 -1
- data/rdoc/RubyXL/Fill.html +1 -1
- data/rdoc/RubyXL/{FontContainer.html → Fills.html} +5 -5
- data/rdoc/RubyXL/FilterContainer.html +1 -1
- data/rdoc/RubyXL/FloatNode.html +1 -1
- data/rdoc/RubyXL/FloatValue.html +1 -1
- data/rdoc/RubyXL/Font.html +1 -1
- data/rdoc/RubyXL/FontScheme.html +1 -1
- data/rdoc/RubyXL/Fonts.html +105 -0
- data/rdoc/RubyXL/FormatScheme.html +1 -1
- data/rdoc/RubyXL/Formula.html +1 -1
- data/rdoc/RubyXL/FunctionGroup.html +1 -1
- data/rdoc/RubyXL/{CellWatchContainer.html → FunctionGroups.html} +5 -5
- data/rdoc/RubyXL/GenericStorage.html +1 -1
- data/rdoc/RubyXL/GradientFill.html +1 -1
- data/rdoc/RubyXL/HeaderFooterSettings.html +1 -1
- data/rdoc/RubyXL/Hyperlink.html +1 -1
- data/rdoc/RubyXL/Hyperlinks.html +105 -0
- data/rdoc/RubyXL/IconFilter.html +1 -1
- data/rdoc/RubyXL/IconSet.html +1 -1
- data/rdoc/RubyXL/IgnoredError.html +1 -1
- data/rdoc/RubyXL/IgnoredErrors.html +105 -0
- data/rdoc/RubyXL/IndexedColors.html +105 -0
- data/rdoc/RubyXL/InputCells.html +1 -1
- data/rdoc/RubyXL/IntegerNode.html +1 -1
- data/rdoc/RubyXL/IntegerValue.html +1 -1
- data/rdoc/RubyXL/LegacyCell.html +1 -1
- data/rdoc/RubyXL/LegacyWorkbook.html +25 -25
- data/rdoc/RubyXL/LegacyWorksheet.html +3 -29
- data/rdoc/RubyXL/{ChartsheetViewContainer.html → MRUColors.html} +5 -5
- data/rdoc/RubyXL/MergedCell.html +1 -1
- data/rdoc/RubyXL/MergedCells.html +2 -2
- data/rdoc/RubyXL/NumFmt.html +1 -1
- data/rdoc/RubyXL/NumberFormat.html +1 -1
- data/rdoc/RubyXL/{NumberFormatContainer.html → NumberFormats.html} +6 -6
- data/rdoc/RubyXL/OLEObject.html +1 -1
- data/rdoc/RubyXL/OLEObjects.html +2 -2
- data/rdoc/RubyXL/OLESize.html +1 -1
- data/rdoc/RubyXL/OOXMLContainerObject.html +105 -0
- data/rdoc/RubyXL/OOXMLObject.html +1 -758
- data/rdoc/RubyXL/OOXMLObjectClassMethods.html +559 -0
- data/rdoc/RubyXL/OOXMLObjectInstanceMethods.html +98 -0
- data/rdoc/RubyXL/OOXMLTopLevelObject.html +1 -1
- data/rdoc/RubyXL/OutlineProperties.html +1 -1
- data/rdoc/RubyXL/PageMargins.html +1 -1
- data/rdoc/RubyXL/PageSetup.html +1 -1
- data/rdoc/RubyXL/PageSetupProperties.html +1 -1
- data/rdoc/RubyXL/Pane.html +1 -1
- data/rdoc/RubyXL/Parser.html +23 -13
- data/rdoc/RubyXL/PatternFill.html +1 -1
- data/rdoc/RubyXL/PhoneticProperties.html +1 -1
- data/rdoc/RubyXL/PhoneticRun.html +1 -1
- data/rdoc/RubyXL/PivotArea.html +1 -1
- data/rdoc/RubyXL/PivotCache.html +1 -1
- data/rdoc/RubyXL/PivotCaches.html +2 -2
- data/rdoc/RubyXL/PivotReference.html +1 -1
- data/rdoc/RubyXL/{CellStyleContainer.html → PivotReferences.html} +5 -5
- data/rdoc/RubyXL/PivotTableSelection.html +1 -1
- data/rdoc/RubyXL/PrintOptions.html +1 -1
- data/rdoc/RubyXL/ProtectedRange.html +1 -1
- data/rdoc/RubyXL/ProtectedRanges.html +2 -2
- data/rdoc/RubyXL/Protection.html +1 -1
- data/rdoc/RubyXL/RID.html +1 -1
- data/rdoc/RubyXL/RawOOXML.html +1 -1
- data/rdoc/RubyXL/Reference.html +1 -1
- data/rdoc/RubyXL/Relationship.html +1 -1
- data/rdoc/RubyXL/RichText.html +1 -1
- data/rdoc/RubyXL/RichTextRun.html +1 -1
- data/rdoc/RubyXL/Row.html +1 -1
- data/rdoc/RubyXL/RunProperties.html +1 -1
- data/rdoc/RubyXL/Scenario.html +1 -1
- data/rdoc/RubyXL/Scenarios.html +105 -0
- data/rdoc/RubyXL/Selection.html +1 -1
- data/rdoc/RubyXL/SharedStringsTable.html +3 -3
- data/rdoc/RubyXL/Sheet.html +1 -1
- data/rdoc/RubyXL/SheetCalculationProperties.html +1 -1
- data/rdoc/RubyXL/SheetData.html +1 -1
- data/rdoc/RubyXL/Sheets.html +2 -2
- data/rdoc/RubyXL/SmartTagProperties.html +1 -1
- data/rdoc/RubyXL/SmartTagType.html +1 -1
- data/rdoc/RubyXL/SmartTagTypes.html +105 -0
- data/rdoc/RubyXL/SmartTags.html +105 -0
- data/rdoc/RubyXL/SortCondition.html +1 -1
- data/rdoc/RubyXL/SortState.html +1 -1
- data/rdoc/RubyXL/Sqref.html +1 -1
- data/rdoc/RubyXL/Stop.html +1 -1
- data/rdoc/RubyXL/StringNode.html +1 -1
- data/rdoc/RubyXL/StringValue.html +1 -1
- data/rdoc/RubyXL/Stylesheet.html +1 -1
- data/rdoc/RubyXL/TableParts.html +2 -2
- data/rdoc/RubyXL/TableStyle.html +1 -1
- data/rdoc/RubyXL/TableStyles.html +2 -2
- data/rdoc/RubyXL/Text.html +1 -1
- data/rdoc/RubyXL/Theme.html +1 -1
- data/rdoc/RubyXL/ThemeElements.html +1 -1
- data/rdoc/RubyXL/Top10.html +1 -1
- data/rdoc/RubyXL/Variant.html +1 -1
- data/rdoc/RubyXL/Vector.html +1 -1
- data/rdoc/RubyXL/VectorValue.html +1 -1
- data/rdoc/RubyXL/WebPublishObject.html +1 -1
- data/rdoc/RubyXL/{WebPublishObjectContainer.html → WebPublishObjects.html} +5 -5
- data/rdoc/RubyXL/WebPublishingItem.html +1 -1
- data/rdoc/RubyXL/{WebPublishingItemContainer.html → WebPublishingItems.html} +5 -5
- data/rdoc/RubyXL/WebPublishingProperties.html +1 -1
- data/rdoc/RubyXL/Workbook.html +1 -1
- data/rdoc/RubyXL/WorkbookProperties.html +1 -1
- data/rdoc/RubyXL/WorkbookProtection.html +1 -1
- data/rdoc/RubyXL/WorkbookRelationships.html +3 -3
- data/rdoc/RubyXL/WorkbookView.html +1 -1
- data/rdoc/RubyXL/WorkbookViews.html +2 -2
- data/rdoc/RubyXL/Worksheet.html +1 -1
- data/rdoc/RubyXL/WorksheetDimensions.html +1 -1
- data/rdoc/RubyXL/WorksheetFormatProperties.html +1 -1
- data/rdoc/RubyXL/WorksheetProperties.html +1 -1
- data/rdoc/RubyXL/WorksheetProtection.html +1 -1
- data/rdoc/RubyXL/WorksheetView.html +1 -1
- data/rdoc/RubyXL/WorksheetViews.html +2 -2
- data/rdoc/RubyXL/Writer.html +1 -1
- data/rdoc/RubyXL/Writer/ContentTypesWriter.html +1 -1
- data/rdoc/RubyXL/Writer/CoreWriter.html +1 -1
- data/rdoc/RubyXL/Writer/GenericWriter.html +1 -1
- data/rdoc/RubyXL/Writer/RootRelsWriter.html +1 -1
- data/rdoc/RubyXL/Writer/StylesWriter.html +1 -1
- data/rdoc/RubyXL/Writer/ThemeWriter.html +1 -1
- data/rdoc/RubyXL/Writer/WorkbookWriter.html +3 -3
- data/rdoc/RubyXL/XF.html +1 -1
- data/rdoc/created.rid +19 -20
- data/rdoc/index.html +4 -6
- data/rdoc/js/search_index.js +1 -1
- data/rdoc/table_of_contents.html +89 -132
- data/rubyXL.gemspec +30 -29
- data/spec/lib/parser_spec.rb +3 -1
- data/spec/lib/stylesheet_spec.rb +1 -1
- metadata +31 -30
- data/lib/rubyXL/writer/worksheet_writer.rb +0 -41
- data/rdoc/RubyXL/CellSmartTagContainer.html +0 -105
- data/rdoc/RubyXL/CustomPropertyContainer.html +0 -105
- data/rdoc/RubyXL/FunctionGroupContainer.html +0 -105
- data/rdoc/RubyXL/HyperlinkContainer.html +0 -105
- data/rdoc/RubyXL/IgnoredErrorContainer.html +0 -105
- data/rdoc/RubyXL/IndexedColorContainer.html +0 -105
- data/rdoc/RubyXL/MRUColorContainer.html +0 -105
- data/rdoc/RubyXL/PivotReferenceContainer.html +0 -105
- data/rdoc/RubyXL/ScenarioContainer.html +0 -105
- data/rdoc/RubyXL/SmartTagContainer.html +0 -105
- data/rdoc/RubyXL/SmartTagTypeContainer.html +0 -105
- data/rdoc/RubyXL/Writer/WorksheetWriter.html +0 -236
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.3.0
|
@@ -52,12 +52,12 @@ module RubyXL
|
|
52
52
|
end
|
53
53
|
|
54
54
|
# http://www.schemacentral.com/sc/ooxml/e-ssml_borders-1.html
|
55
|
-
class
|
56
|
-
define_child_node(RubyXL::Border, :collection => :with_count
|
55
|
+
class Borders < OOXMLContainerObject
|
56
|
+
define_child_node(RubyXL::Border, :collection => :with_count)
|
57
57
|
define_element_name 'borders'
|
58
58
|
|
59
59
|
def self.defaults
|
60
|
-
self.new(:
|
60
|
+
self.new(:_ => [ RubyXL::Border.new ])
|
61
61
|
end
|
62
62
|
|
63
63
|
end
|
@@ -49,8 +49,8 @@ module RubyXL
|
|
49
49
|
end
|
50
50
|
|
51
51
|
# http://www.schemacentral.com/sc/ooxml/e-ssml_sheetViews-4.html
|
52
|
-
class
|
53
|
-
define_child_node(RubyXL::ChartsheetView, :collection => true
|
52
|
+
class ChartsheetViews < OOXMLObject
|
53
|
+
define_child_node(RubyXL::ChartsheetView, :collection => true)
|
54
54
|
define_child_node(RubyXL::ExtensionStorageArea)
|
55
55
|
define_element_name 'sheetViews'
|
56
56
|
end
|
@@ -58,9 +58,9 @@ module RubyXL
|
|
58
58
|
# http://www.schemacentral.com/sc/ooxml/e-ssml_chartsheet.html
|
59
59
|
class Chartsheet < OOXMLTopLevelObject
|
60
60
|
define_child_node(RubyXL::ChartsheetProperties)
|
61
|
-
define_child_node(RubyXL::
|
61
|
+
define_child_node(RubyXL::ChartsheetViews)
|
62
62
|
define_child_node(RubyXL::ChartsheetProtection)
|
63
|
-
define_child_node(RubyXL::CustomSheetViews
|
63
|
+
define_child_node(RubyXL::CustomSheetViews)
|
64
64
|
define_child_node(RubyXL::PageMargins)
|
65
65
|
define_child_node(RubyXL::ChartsheetPageSetup)
|
66
66
|
define_child_node(RubyXL::HeaderFooterSettings)
|
@@ -68,11 +68,26 @@ module RubyXL
|
|
68
68
|
define_child_node(RubyXL::RID, :node_name => :legacyDrawing)
|
69
69
|
define_child_node(RubyXL::RID, :node_name => :legacyDrawingHF)
|
70
70
|
define_child_node(RubyXL::RID, :node_name => :picture)
|
71
|
-
define_child_node(RubyXL::
|
71
|
+
define_child_node(RubyXL::WebPublishingItems)
|
72
72
|
define_child_node(RubyXL::ExtensionStorageArea)
|
73
73
|
define_element_name 'chartsheet'
|
74
74
|
set_namespaces('xmlns' => 'http://schemas.openxmlformats.org/spreadsheetml/2006/main',
|
75
75
|
'xmlns:r' => 'http://schemas.openxmlformats.org/officeDocument/2006/relationships')
|
76
|
+
|
77
|
+
def sheet_index
|
78
|
+
@workbook.worksheets.select{ |sheet| sheet.is_a?(self.class) }.index{ |sheet| sheet.equal?(self) }
|
79
|
+
end
|
80
|
+
|
81
|
+
def filepath
|
82
|
+
File.join('xl', 'chartsheets', "sheet#{sheet_index + 1}.xml")
|
83
|
+
end
|
84
|
+
|
85
|
+
def rel_type
|
86
|
+
'chartsheet'
|
87
|
+
end
|
88
|
+
|
89
|
+
attr_accessor :workbook, :sheet_name, :sheet_id
|
90
|
+
|
76
91
|
end
|
77
92
|
|
78
93
|
end
|
data/lib/rubyXL/objects/fill.rb
CHANGED
@@ -39,12 +39,12 @@ module RubyXL
|
|
39
39
|
end
|
40
40
|
|
41
41
|
# http://www.schemacentral.com/sc/ooxml/e-ssml_fills-1.html
|
42
|
-
class
|
43
|
-
define_child_node(RubyXL::Fill, :collection => :with_count
|
42
|
+
class Fills < OOXMLContainerObject
|
43
|
+
define_child_node(RubyXL::Fill, :collection => :with_count)
|
44
44
|
define_element_name 'fills'
|
45
45
|
|
46
46
|
def self.defaults
|
47
|
-
self.new(:
|
47
|
+
self.new(:_ => [
|
48
48
|
RubyXL::Fill.new(:pattern_fill => RubyXL::PatternFill.new(:pattern_type => 'none')),
|
49
49
|
RubyXL::Fill.new(:pattern_fill => RubyXL::PatternFill.new(:pattern_type => 'gray125'))
|
50
50
|
])
|
@@ -20,7 +20,7 @@ module RubyXL
|
|
20
20
|
class FilterContainer < OOXMLObject
|
21
21
|
define_attribute(:blank, :bool, :default => false)
|
22
22
|
define_attribute(:calendarType, RubyXL::ST_CalendarType, :default => 'none')
|
23
|
-
define_child_node(RubyXL::StringValue,
|
23
|
+
define_child_node(RubyXL::StringValue, :collection => true, :accessor => :filters, :node_name => :filter)
|
24
24
|
define_child_node(RubyXL::DateGroupItem, :collection => true, :accessor => :date_group_items)
|
25
25
|
define_element_name 'filters'
|
26
26
|
end
|
@@ -42,9 +42,9 @@ module RubyXL
|
|
42
42
|
end
|
43
43
|
|
44
44
|
# http://www.schemacentral.com/sc/ooxml/e-ssml_customFilters-1.html
|
45
|
-
class
|
46
|
-
define_attribute(:and, :bool, :default
|
47
|
-
define_child_node(RubyXL::CustomFilter, :collection => true
|
45
|
+
class CustomFilters < OOXMLContainerObject
|
46
|
+
define_attribute(:and, :bool, :default => false)
|
47
|
+
define_child_node(RubyXL::CustomFilter, :collection => true)
|
48
48
|
define_element_name 'customFilters'
|
49
49
|
end
|
50
50
|
|
@@ -77,7 +77,7 @@ module RubyXL
|
|
77
77
|
define_attribute(:showButton, :bool, :default => true)
|
78
78
|
define_child_node(RubyXL::FilterContainer)
|
79
79
|
define_child_node(RubyXL::Top10)
|
80
|
-
define_child_node(RubyXL::
|
80
|
+
define_child_node(RubyXL::CustomFilters)
|
81
81
|
define_child_node(RubyXL::DynamicFilter)
|
82
82
|
define_child_node(RubyXL::ColorFilter)
|
83
83
|
define_child_node(RubyXL::IconFilter)
|
data/lib/rubyXL/objects/font.rb
CHANGED
@@ -94,12 +94,12 @@ module RubyXL
|
|
94
94
|
end
|
95
95
|
|
96
96
|
# http://www.schemacentral.com/sc/ooxml/e-ssml_fonts-1.html
|
97
|
-
class
|
98
|
-
define_child_node(RubyXL::Font, :collection => :with_count
|
97
|
+
class Fonts < OOXMLContainerObject
|
98
|
+
define_child_node(RubyXL::Font, :collection => :with_count)
|
99
99
|
define_element_name 'fonts'
|
100
100
|
|
101
101
|
def self.defaults
|
102
|
-
self.new(:
|
102
|
+
self.new(:_ => [
|
103
103
|
RubyXL::Font.new(:name => RubyXL::StringValue.new(:val => 'Verdana'),
|
104
104
|
:sz => RubyXL::FloatValue.new(:val => 10) ),
|
105
105
|
RubyXL::Font.new(:name => RubyXL::StringValue.new(:val => 'Verdana'),
|
@@ -1,9 +1,5 @@
|
|
1
1
|
module RubyXL
|
2
|
-
|
3
|
-
# Parent class for defining OOXML based objects (not unlike Rails' +ActiveRecord+!)
|
4
|
-
# Most importantly, provides functionality of parsing such objects from XML,
|
5
|
-
# and marshalling them to XML.
|
6
|
-
class OOXMLObject
|
2
|
+
module OOXMLObjectClassMethods
|
7
3
|
# Get the value of a [sub]class variable if it exists, or create the respective variable
|
8
4
|
# with the passed-in +default+ (or +{}+, if not specified)
|
9
5
|
#
|
@@ -12,7 +8,7 @@ module RubyXL
|
|
12
8
|
# addressing variable by name creates it in the context of defining class, while calling
|
13
9
|
# the setter/getter method addresses it in the context of descendant class,
|
14
10
|
# which is what we need.
|
15
|
-
def
|
11
|
+
def obtain_class_variable(var_name, default = {})
|
16
12
|
if class_variable_defined?(var_name) then
|
17
13
|
self.class_variable_get(var_name)
|
18
14
|
else
|
@@ -20,11 +16,6 @@ module RubyXL
|
|
20
16
|
end
|
21
17
|
end
|
22
18
|
|
23
|
-
def obtain_class_variable(var_name, default = {})
|
24
|
-
self.class.obtain_class_variable(var_name, default)
|
25
|
-
end
|
26
|
-
private :obtain_class_variable
|
27
|
-
|
28
19
|
# Defines an attribute of OOXML object.
|
29
20
|
# === Parameters
|
30
21
|
# * +attribute_name+ - Name of the element attribute as seen in the source XML. Can be either <tt>"String"</tt> or <tt>:Symbol</tt>
|
@@ -41,6 +32,7 @@ module RubyXL
|
|
41
32
|
# * +:accessor+ - Name of the accessor for this attribute to be defined on the object. If not provided, defaults to classidied +attribute_name+.
|
42
33
|
# * +:default+ - Value this attribute defaults to if not explicitly provided.
|
43
34
|
# * +:required+ - Whether this attribute is required when writing XML. If the value of the attrinute is not explicitly provided, +:default+ is written instead.
|
35
|
+
# * +:computed+ - Do not store this attribute on +parse+, but do call the object-provided read accessor on +write_xml+.
|
44
36
|
# ==== Examples
|
45
37
|
# define_attribute(:outline, :bool, :default => true)
|
46
38
|
# A <tt>Boolean</tt> attribute 'outline' with default value +true+ will be accessible by calling +obj.outline+
|
@@ -48,32 +40,16 @@ module RubyXL
|
|
48
40
|
# An <tt>Integer</tt> attribute 'uniqueCount' accessible as +obj.unique_count+
|
49
41
|
# define_attribute(:_, :string, :accessor => :expression)
|
50
42
|
# The value of the element will be accessible as a <tt>String</tt> by calling +obj.expression+
|
51
|
-
# define_attribute(:errorStyle,
|
43
|
+
# define_attribute(:errorStyle, %w{ stop warning information }, :default => 'stop',)
|
52
44
|
# A <tt>String</tt> attribute named 'errorStyle' will be accessible as +obj.error_style+, valid values are <tt>"stop"</tt>, <tt>"warning"</tt>, <tt>"information"</tt>
|
53
|
-
def
|
45
|
+
def define_attribute(attr_name, attr_type, extra_params = {})
|
54
46
|
attrs = obtain_class_variable(:@@ooxml_attributes)
|
55
|
-
|
56
|
-
|
57
|
-
attr_name =
|
58
|
-
|
59
|
-
attr_hash = {
|
60
|
-
:accessor => accessor,
|
61
|
-
:attr_type => attr_type,
|
62
|
-
:optional => !extra_params[:required],
|
63
|
-
:default => extra_params[:default],
|
64
|
-
}
|
65
|
-
|
66
|
-
if attr_type.is_a?(Array) then
|
67
|
-
attr_hash[:values] = attr_type
|
68
|
-
attr_hash[:attr_type] = :string
|
69
|
-
end
|
70
|
-
|
71
|
-
|
72
|
-
attrs[attr_name] = attr_hash
|
73
|
-
|
74
|
-
self.send(:attr_accessor, accessor)
|
47
|
+
attr_hash = extra_params.merge({ :attr_type => attr_type })
|
48
|
+
attr_hash[:accessor] ||= accessorize(attr_name)
|
49
|
+
attrs[attr_name.to_s] = attr_hash
|
50
|
+
self.send(:attr_accessor, attr_hash[:accessor]) unless attr_hash[:computed]
|
75
51
|
end
|
76
|
-
|
52
|
+
|
77
53
|
# Defines a child node of OOXML object.
|
78
54
|
# === Parameters
|
79
55
|
# * +klass+ - Class (descendant of RubyXL::OOXMLObject) of the child nodes. Child node objects will be produced by calling +parse+ method of that class.
|
@@ -94,7 +70,7 @@ module RubyXL
|
|
94
70
|
# Use class RubyXL::BorderEdge when parsing both the elements <tt><left ...></tt> and <tt><right ...></tt> elements.
|
95
71
|
# define_child_node(RubyXL::Font, :collection => :with_count, :accessor => :fonts)
|
96
72
|
# Upon writing of the object this was defined on, its <tt>count</tt> attribute will be set to the count of nodes in <tt>fonts</tt> array
|
97
|
-
def
|
73
|
+
def define_child_node(klass, extra_params = {})
|
98
74
|
child_nodes = obtain_class_variable(:@@ooxml_child_nodes)
|
99
75
|
child_node_name = (extra_params[:node_name] || klass.class_variable_get(:@@ooxml_tag_name)).to_s
|
100
76
|
accessor = (extra_params[:accessor] || accessorize(child_node_name)).to_sym
|
@@ -105,13 +81,16 @@ module RubyXL
|
|
105
81
|
:accessor => accessor
|
106
82
|
}
|
107
83
|
|
108
|
-
if extra_params[:collection] == :with_count
|
109
|
-
define_attribute(:count, :int, :required => true)
|
110
|
-
end
|
84
|
+
define_count_attribute if extra_params[:collection] == :with_count
|
111
85
|
|
112
86
|
self.send(:attr_accessor, accessor)
|
113
87
|
end
|
114
88
|
|
89
|
+
def define_count_attribute
|
90
|
+
define_attribute(:count, :int, :required => true)
|
91
|
+
end
|
92
|
+
private :define_count_attribute
|
93
|
+
|
115
94
|
# Defines the name of the element that represents the current OOXML object. Should only be used once per object.
|
116
95
|
# In case of different objects represented by the same class in different parts of OOXML tree, +:node_name+
|
117
96
|
# extra parameter can be used to override the default element name.
|
@@ -119,92 +98,17 @@ module RubyXL
|
|
119
98
|
# * +element_name+
|
120
99
|
# ==== Examples
|
121
100
|
# define_element_name 'externalReference'
|
122
|
-
def
|
101
|
+
def define_element_name(element_name)
|
123
102
|
self.class_variable_set(:@@ooxml_tag_name, element_name)
|
124
103
|
end
|
125
104
|
|
126
105
|
# #TODO# This method will eventually be obsoleted.
|
127
|
-
def
|
106
|
+
def set_countable
|
128
107
|
self.class_variable_set(:@@ooxml_countable, true)
|
129
108
|
self.send(:attr_accessor, :count)
|
130
109
|
end
|
131
110
|
|
132
|
-
|
133
|
-
# generation, +before_write_xml()+ is called to perform last-minute cleanup and validation operations; if it
|
134
|
-
# returns +false+, an empty string is returned (rather than +nil+, so Nokogiri::XML's <tt><<</tt> operator
|
135
|
-
# can be used without additional +nil+ checking)
|
136
|
-
# === Parameters
|
137
|
-
# * +xml+ - Base Nokogiri::XML object used for building. If omitted, a blank document will be generated.
|
138
|
-
# * +node_name_override+ - if present, is used instead of the default element name for this object provided by +define_element_name+
|
139
|
-
# ==== Examples
|
140
|
-
# obj.write_xml
|
141
|
-
# Creates a new Nokogiti::XML and
|
142
|
-
def write_xml(xml = nil, node_name_override = nil)
|
143
|
-
if xml.nil? then
|
144
|
-
seed_xml = Nokogiri::XML('<?xml version = "1.0" standalone ="yes"?>')
|
145
|
-
seed_xml.encoding = 'UTF-8'
|
146
|
-
result = self.write_xml(seed_xml)
|
147
|
-
return result if result == ''
|
148
|
-
seed_xml << result
|
149
|
-
return seed_xml.to_xml({ :indent => 0, :save_with => Nokogiri::XML::Node::SaveOptions::AS_XML })
|
150
|
-
end
|
151
|
-
|
152
|
-
return '' unless before_write_xml
|
153
|
-
|
154
|
-
attrs = obtain_class_variable(:@@ooxml_namespaces).dup
|
155
|
-
|
156
|
-
obtain_class_variable(:@@ooxml_attributes).each_pair { |k, v|
|
157
|
-
val = self.send(v[:accessor])
|
158
|
-
|
159
|
-
if val.nil? then
|
160
|
-
next if v[:optional]
|
161
|
-
val = v[:default]
|
162
|
-
end
|
163
|
-
|
164
|
-
val = val &&
|
165
|
-
case v[:attr_type]
|
166
|
-
when :bool then val ? '1' : '0'
|
167
|
-
when :float then val.to_s.gsub(/\.0*$/, '') # Trim trailing zeroes
|
168
|
-
else val
|
169
|
-
end
|
170
|
-
|
171
|
-
attrs[k] = val
|
172
|
-
}
|
173
|
-
|
174
|
-
element_text = attrs.delete('_')
|
175
|
-
elem = xml.create_element(node_name_override || obtain_class_variable(:@@ooxml_tag_name), attrs, element_text)
|
176
|
-
child_nodes = obtain_class_variable(:@@ooxml_child_nodes)
|
177
|
-
child_nodes.each_pair { |child_node_name, child_node_params|
|
178
|
-
obj = self.send(child_node_params[:accessor])
|
179
|
-
unless obj.nil?
|
180
|
-
if child_node_params[:is_array] then obj.each { |item| elem << item.write_xml(xml, child_node_name) unless item.nil? }
|
181
|
-
else elem << obj.write_xml(xml, child_node_name)
|
182
|
-
end
|
183
|
-
end
|
184
|
-
}
|
185
|
-
elem
|
186
|
-
end
|
187
|
-
|
188
|
-
def initialize(params = {})
|
189
|
-
obtain_class_variable(:@@ooxml_attributes).each_value { |v|
|
190
|
-
instance_variable_set("@#{v[:accessor]}", params[v[:accessor]])
|
191
|
-
}
|
192
|
-
|
193
|
-
obtain_class_variable(:@@ooxml_child_nodes).each_value { |v|
|
194
|
-
|
195
|
-
initial_value =
|
196
|
-
if params.has_key?(v[:accessor]) then params[v[:accessor]]
|
197
|
-
elsif v[:is_array] then []
|
198
|
-
else nil
|
199
|
-
end
|
200
|
-
|
201
|
-
instance_variable_set("@#{v[:accessor]}", initial_value)
|
202
|
-
}
|
203
|
-
|
204
|
-
instance_variable_set("@count", 0) if obtain_class_variable(:@@ooxml_countable, false)
|
205
|
-
end
|
206
|
-
|
207
|
-
def self.parse(node)
|
111
|
+
def parse(node)
|
208
112
|
node = Nokogiri::XML.parse(node) if node.is_a?(IO) || node.is_a?(String)
|
209
113
|
|
210
114
|
if node.is_a?(Nokogiri::XML::Document) then
|
@@ -230,7 +134,7 @@ module RubyXL
|
|
230
134
|
|
231
135
|
next if attr_params.nil?
|
232
136
|
# raise "Unknown attribute: #{attr_name}" if attr_params.nil?
|
233
|
-
process_attribute(obj, attr.value, attr_params)
|
137
|
+
process_attribute(obj, attr.value, attr_params) unless attr_params[:computed]
|
234
138
|
}
|
235
139
|
|
236
140
|
known_child_nodes = obtain_class_variable(:@@ooxml_child_nodes)
|
@@ -248,7 +152,11 @@ module RubyXL
|
|
248
152
|
parsed_object = child_node_params[:class].parse(child_node)
|
249
153
|
if child_node_params[:is_array] then
|
250
154
|
index = parsed_object.index_in_collection
|
251
|
-
|
155
|
+
|
156
|
+
collection = if (self < RubyXL::OOXMLContainerObject) then obj
|
157
|
+
else obj.send(child_node_params[:accessor])
|
158
|
+
end
|
159
|
+
|
252
160
|
if index.nil? then
|
253
161
|
collection << parsed_object
|
254
162
|
else
|
@@ -263,6 +171,126 @@ module RubyXL
|
|
263
171
|
obj
|
264
172
|
end
|
265
173
|
|
174
|
+
private
|
175
|
+
def accessorize(str)
|
176
|
+
acc = str.to_s.dup
|
177
|
+
acc.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
|
178
|
+
acc.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
179
|
+
acc.gsub!(':','_')
|
180
|
+
acc.downcase.to_sym
|
181
|
+
end
|
182
|
+
|
183
|
+
def process_attribute(obj, raw_value, params)
|
184
|
+
val = raw_value &&
|
185
|
+
case params[:attr_type]
|
186
|
+
when :int then Integer(raw_value)
|
187
|
+
when :float then Float(raw_value)
|
188
|
+
when :string then raw_value
|
189
|
+
when Array then raw_value # Case of Simple Types
|
190
|
+
when :sqref then RubyXL::Sqref.new(raw_value)
|
191
|
+
when :ref then RubyXL::Reference.new(raw_value)
|
192
|
+
when :bool then ['1', 'true'].include?(raw_value)
|
193
|
+
end
|
194
|
+
obj.send("#{params[:accessor]}=", val)
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|
198
|
+
|
199
|
+
|
200
|
+
module OOXMLObjectInstanceMethods
|
201
|
+
|
202
|
+
def obtain_class_variable(var_name, default = {})
|
203
|
+
self.class.obtain_class_variable(var_name, default)
|
204
|
+
end
|
205
|
+
private :obtain_class_variable
|
206
|
+
|
207
|
+
def initialize(params = {})
|
208
|
+
obtain_class_variable(:@@ooxml_attributes).each_value { |v|
|
209
|
+
instance_variable_set("@#{v[:accessor]}", params[v[:accessor]]) unless v[:computed]
|
210
|
+
}
|
211
|
+
|
212
|
+
init_child_nodes(params)
|
213
|
+
|
214
|
+
instance_variable_set("@count", 0) if obtain_class_variable(:@@ooxml_countable, false)
|
215
|
+
end
|
216
|
+
|
217
|
+
def init_child_nodes(params)
|
218
|
+
obtain_class_variable(:@@ooxml_child_nodes).each_value { |v|
|
219
|
+
|
220
|
+
initial_value =
|
221
|
+
if params.has_key?(v[:accessor]) then params[v[:accessor]]
|
222
|
+
elsif v[:is_array] then []
|
223
|
+
else nil
|
224
|
+
end
|
225
|
+
|
226
|
+
instance_variable_set("@#{v[:accessor]}", initial_value)
|
227
|
+
}
|
228
|
+
end
|
229
|
+
private :init_child_nodes
|
230
|
+
|
231
|
+
# Recursively write the OOXML object and all its children out as Nokogiri::XML. Immediately before the actual
|
232
|
+
# generation, +before_write_xml()+ is called to perform last-minute cleanup and validation operations; if it
|
233
|
+
# returns +false+, an empty string is returned (rather than +nil+, so Nokogiri::XML's <tt><<</tt> operator
|
234
|
+
# can be used without additional +nil+ checking)
|
235
|
+
# === Parameters
|
236
|
+
# * +xml+ - Base Nokogiri::XML object used for building. If omitted, a blank document will be generated.
|
237
|
+
# * +node_name_override+ - if present, is used instead of the default element name for this object provided by +define_element_name+
|
238
|
+
# ==== Examples
|
239
|
+
# obj.write_xml
|
240
|
+
# Creates a new Nokogiti::XML and
|
241
|
+
def write_xml(xml = nil, node_name_override = nil)
|
242
|
+
if xml.nil? then
|
243
|
+
seed_xml = Nokogiri::XML('<?xml version = "1.0" standalone ="yes"?>')
|
244
|
+
seed_xml.encoding = 'UTF-8'
|
245
|
+
result = self.write_xml(seed_xml)
|
246
|
+
return result if result == ''
|
247
|
+
seed_xml << result
|
248
|
+
return seed_xml.to_xml({ :indent => 0, :save_with => Nokogiri::XML::Node::SaveOptions::AS_XML })
|
249
|
+
end
|
250
|
+
|
251
|
+
return '' unless before_write_xml
|
252
|
+
|
253
|
+
attrs = obtain_class_variable(:@@ooxml_namespaces).dup
|
254
|
+
|
255
|
+
obtain_class_variable(:@@ooxml_attributes).each_pair { |k, v|
|
256
|
+
val = self.send(v[:accessor])
|
257
|
+
|
258
|
+
if val.nil? then
|
259
|
+
next unless v[:required]
|
260
|
+
val = v[:default]
|
261
|
+
end
|
262
|
+
|
263
|
+
val = val &&
|
264
|
+
case v[:attr_type]
|
265
|
+
when :bool then val ? '1' : '0'
|
266
|
+
when :float then val.to_s.gsub(/\.0*$/, '') # Trim trailing zeroes
|
267
|
+
else val
|
268
|
+
end
|
269
|
+
|
270
|
+
attrs[k] = val
|
271
|
+
}
|
272
|
+
|
273
|
+
element_text = attrs.delete('_')
|
274
|
+
elem = xml.create_element(node_name_override || obtain_class_variable(:@@ooxml_tag_name), attrs, element_text)
|
275
|
+
|
276
|
+
child_nodes = obtain_class_variable(:@@ooxml_child_nodes)
|
277
|
+
child_nodes.each_pair { |child_node_name, child_node_params|
|
278
|
+
node_obj = get_node_object(child_node_params)
|
279
|
+
next if node_obj.nil?
|
280
|
+
|
281
|
+
if node_obj.respond_to?(:write_xml) && !node_obj.equal?(self) then
|
282
|
+
# If child node is either +OOXMLObject+, or +OOXMLContainerObject+ on its first (envelope) pass,
|
283
|
+
# serialize that object.
|
284
|
+
elem << node_obj.write_xml(xml, child_node_name)
|
285
|
+
else
|
286
|
+
# If child node is either vanilla +Array+, or +OOXMLContainerObject+ on its seconds (content) pass,
|
287
|
+
# serialize write its members.
|
288
|
+
node_obj.each { |item| elem << item.write_xml(xml, child_node_name) unless item.nil? }
|
289
|
+
end
|
290
|
+
}
|
291
|
+
elem
|
292
|
+
end
|
293
|
+
|
266
294
|
def dup
|
267
295
|
new_copy = super
|
268
296
|
new_copy.count = 0 if obtain_class_variable(:@@ooxml_countable, false)
|
@@ -276,10 +304,16 @@ module RubyXL
|
|
276
304
|
nil
|
277
305
|
end
|
278
306
|
|
307
|
+
def get_node_object(child_node_params)
|
308
|
+
self.send(child_node_params[:accessor])
|
309
|
+
end
|
310
|
+
private :get_node_object
|
311
|
+
|
279
312
|
# Subclass provided filter to perform last-minute operations (cleanup, count, etc.) immediately prior to write,
|
280
313
|
# along with option to terminate the actual write if +false+ is returned (for example, to avoid writing
|
281
314
|
# the collection's root node if the collection is empty).
|
282
315
|
def before_write_xml
|
316
|
+
#TODO# This will go away once containers are fully implemented.
|
283
317
|
child_nodes = obtain_class_variable(:@@ooxml_child_nodes)
|
284
318
|
child_nodes.each_pair { |child_node_name, child_node_params|
|
285
319
|
self.count = self.send(child_node_params[:accessor]).size if child_node_params[:is_array] == :with_count
|
@@ -287,36 +321,73 @@ module RubyXL
|
|
287
321
|
true
|
288
322
|
end
|
289
323
|
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
324
|
+
end
|
325
|
+
|
326
|
+
# Parent class for defining OOXML based objects (not unlike Rails' +ActiveRecord+!)
|
327
|
+
# Most importantly, provides functionality of parsing such objects from XML,
|
328
|
+
# and marshalling them to XML.
|
329
|
+
class OOXMLObject
|
330
|
+
include OOXMLObjectInstanceMethods
|
331
|
+
extend OOXMLObjectClassMethods
|
332
|
+
end
|
333
|
+
|
334
|
+
# Parent class for OOXML conainer objects (for example,
|
335
|
+
# <tt><fonts><font>...</font><font>...</font></fonts></tt>
|
336
|
+
# that obscures the top-level container, allowing direct access to the contents as +Array+.
|
337
|
+
class OOXMLContainerObject < Array
|
338
|
+
include OOXMLObjectInstanceMethods
|
339
|
+
extend OOXMLObjectClassMethods
|
340
|
+
|
341
|
+
def initialize(params = {})
|
342
|
+
array_content = params.delete(:_)
|
343
|
+
super
|
344
|
+
array_content.each_with_index { |v, i| self[i] = v } if array_content
|
297
345
|
end
|
298
346
|
|
299
|
-
def
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
347
|
+
def get_node_object(child_node_params)
|
348
|
+
if child_node_params[:is_array] then self
|
349
|
+
else super
|
350
|
+
end
|
351
|
+
end
|
352
|
+
protected :get_node_object
|
353
|
+
|
354
|
+
def init_child_nodes(params)
|
355
|
+
obtain_class_variable(:@@ooxml_child_nodes).each_value { |v|
|
356
|
+
next if v[:is_array] # Only one collection node allowed per OOXMLContainerObject, and it is contained in itself.
|
357
|
+
instance_variable_set("@#{v[:accessor]}", params[v[:accessor]])
|
358
|
+
}
|
359
|
+
end
|
360
|
+
protected :init_child_nodes
|
361
|
+
|
362
|
+
def before_write_xml
|
363
|
+
true
|
364
|
+
end
|
365
|
+
|
366
|
+
def inspect
|
367
|
+
vars = [ super ]
|
368
|
+
vars = self.instance_variables.each { |v| vars << "#{v}=#{instance_variable_get(v).inspect}" }
|
369
|
+
"<#{self.class}: #{super} #{vars.join(", ")}>"
|
370
|
+
end
|
371
|
+
|
372
|
+
class << self
|
373
|
+
def define_count_attribute
|
374
|
+
# Count will be inherited from Array. so no need to define it explicitly.
|
375
|
+
define_attribute(:count, :int, :required => true, :computed => true)
|
376
|
+
end
|
377
|
+
protected :define_count_attribute
|
310
378
|
end
|
311
379
|
|
312
380
|
end
|
313
381
|
|
314
382
|
# Extension class providing functionality for top-level OOXML objects that are represented by
|
315
383
|
# their own <tt>.xml</tt> files in <tt>.xslx</tt> zip container.
|
316
|
-
|
317
384
|
class OOXMLTopLevelObject < OOXMLObject
|
318
385
|
# Prototype method. For top-level OOXML object, returns the path at which the current object's XML file
|
319
386
|
# is located within the <tt>.xslx</tt> zip container.
|
387
|
+
def filepath
|
388
|
+
self.class.filepath
|
389
|
+
end
|
390
|
+
|
320
391
|
def self.filepath
|
321
392
|
raise 'Subclass responsebility'
|
322
393
|
end
|
@@ -347,7 +418,7 @@ module RubyXL
|
|
347
418
|
def add_to_zip(zipfile)
|
348
419
|
xml_string = write_xml
|
349
420
|
return if xml_string.empty?
|
350
|
-
zipfile.get_output_stream(self.
|
421
|
+
zipfile.get_output_stream(self.filepath) { |f| f << xml_string }
|
351
422
|
end
|
352
423
|
|
353
424
|
end
|