rubyXL 1.2.10 → 3.4.33
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.
- checksums.yaml +7 -0
- data/.circleci/config.yml +60 -0
- data/.codeclimate.yml +3 -0
- data/.rubocop.yml +124 -0
- data/CHANGELOG.md +12 -0
- data/Gemfile +18 -14
- data/LICENSE.txt +1 -1
- data/README.rdoc +170 -100
- data/Rakefile +76 -26
- data/VERSION +1 -1
- data/lib/rubyXL/cell.rb +13 -447
- data/lib/rubyXL/convenience_methods/cell.rb +276 -0
- data/lib/rubyXL/convenience_methods/color.rb +156 -0
- data/lib/rubyXL/convenience_methods/font.rb +63 -0
- data/lib/rubyXL/convenience_methods/workbook.rb +137 -0
- data/lib/rubyXL/convenience_methods/worksheet.rb +734 -0
- data/lib/rubyXL/convenience_methods.rb +5 -0
- data/lib/rubyXL/objects/border.rb +71 -0
- data/lib/rubyXL/objects/calculation_chain.rb +31 -0
- data/lib/rubyXL/objects/cell_style.rb +63 -0
- data/lib/rubyXL/objects/chartsheet.rb +88 -0
- data/lib/rubyXL/objects/color.rb +25 -0
- data/lib/rubyXL/objects/column_range.rb +93 -0
- data/lib/rubyXL/objects/comments.rb +44 -0
- data/lib/rubyXL/objects/connection.rb +175 -0
- data/lib/rubyXL/objects/container_nodes.rb +131 -0
- data/lib/rubyXL/objects/content_types.rb +74 -0
- data/lib/rubyXL/objects/data_validation.rb +37 -0
- data/lib/rubyXL/objects/document_properties.rb +156 -0
- data/lib/rubyXL/objects/extensions.rb +51 -0
- data/lib/rubyXL/objects/external_links.rb +115 -0
- data/lib/rubyXL/objects/fill.rb +52 -0
- data/lib/rubyXL/objects/filters.rb +118 -0
- data/lib/rubyXL/objects/font.rb +43 -0
- data/lib/rubyXL/objects/formula.rb +22 -0
- data/lib/rubyXL/objects/ooxml_object.rb +469 -0
- data/lib/rubyXL/objects/query_table.rb +106 -0
- data/lib/rubyXL/objects/reference.rb +119 -0
- data/lib/rubyXL/objects/relationships.rb +213 -0
- data/lib/rubyXL/objects/root.rb +84 -0
- data/lib/rubyXL/objects/shared_strings.rb +67 -0
- data/lib/rubyXL/objects/sheet_common.rb +49 -0
- data/lib/rubyXL/objects/sheet_data.rb +219 -0
- data/lib/rubyXL/objects/simple_types.rb +249 -0
- data/lib/rubyXL/objects/storage.rb +193 -0
- data/lib/rubyXL/objects/stylesheet.rb +224 -0
- data/lib/rubyXL/objects/text.rb +92 -0
- data/lib/rubyXL/objects/theme.rb +1730 -0
- data/lib/rubyXL/objects/workbook.rb +572 -0
- data/lib/rubyXL/objects/worksheet.rb +762 -0
- data/lib/rubyXL/parser.rb +18 -459
- data/lib/rubyXL/worksheet.rb +73 -1461
- data/lib/rubyXL.rb +9 -7
- data/rdoc/README_rdoc.html +534 -0
- data/rdoc/RubyXL/AExtension.html +187 -0
- data/rdoc/RubyXL/AExtensionStorageArea.html +97 -0
- data/rdoc/RubyXL/ActiveX.html +156 -0
- data/rdoc/RubyXL/ActiveXBinary.html +106 -0
- data/rdoc/RubyXL/AdjustHandleList.html +99 -0
- data/rdoc/RubyXL/Alignment.html +99 -0
- data/rdoc/RubyXL/AlternateContent.html +97 -0
- data/rdoc/RubyXL/AlternateUrls.html +99 -0
- data/rdoc/RubyXL/Authors.html +99 -0
- data/rdoc/RubyXL/AutoFilter.html +99 -0
- data/rdoc/RubyXL/AutoFilterColumn.html +99 -0
- data/rdoc/RubyXL/BinaryImageFile.html +108 -0
- data/rdoc/RubyXL/BodyProperties.html +99 -0
- data/rdoc/RubyXL/BooleanNode.html +97 -0
- data/rdoc/RubyXL/BooleanValue.html +97 -0
- data/rdoc/RubyXL/Border.html +223 -0
- data/rdoc/RubyXL/BorderEdge.html +160 -0
- data/rdoc/RubyXL/Borders.html +138 -0
- data/rdoc/RubyXL/Break.html +99 -0
- data/rdoc/RubyXL/BreakList.html +99 -0
- data/rdoc/RubyXL/CT_AdjPoint2D.html +99 -0
- data/rdoc/RubyXL/CT_AlphaBiLevelEffect.html +99 -0
- data/rdoc/RubyXL/CT_AlphaModulateEffect.html +99 -0
- data/rdoc/RubyXL/CT_AlphaModulateFixedEffect.html +99 -0
- data/rdoc/RubyXL/CT_AlphaOutsetEffect.html +99 -0
- data/rdoc/RubyXL/CT_AlphaReplaceEffect.html +99 -0
- data/rdoc/RubyXL/CT_Backdrop.html +99 -0
- data/rdoc/RubyXL/CT_Bevel.html +99 -0
- data/rdoc/RubyXL/CT_BiLevelEffect.html +99 -0
- data/rdoc/RubyXL/CT_BlendEffect.html +99 -0
- data/rdoc/RubyXL/CT_Blip.html +99 -0
- data/rdoc/RubyXL/CT_BlipFillProperties.html +99 -0
- data/rdoc/RubyXL/CT_BlurEffect.html +99 -0
- data/rdoc/RubyXL/CT_Camera.html +99 -0
- data/rdoc/RubyXL/CT_Color.html +99 -0
- data/rdoc/RubyXL/CT_ColorChangeEffect.html +99 -0
- data/rdoc/RubyXL/CT_ColorMapping.html +99 -0
- data/rdoc/RubyXL/CT_ColorScheme.html +99 -0
- data/rdoc/RubyXL/CT_ColorSchemeAndMapping.html +99 -0
- data/rdoc/RubyXL/CT_ConnectionSite.html +99 -0
- data/rdoc/RubyXL/CT_ConnectionSiteList.html +99 -0
- data/rdoc/RubyXL/CT_DashStop.html +99 -0
- data/rdoc/RubyXL/CT_DashStopList.html +99 -0
- data/rdoc/RubyXL/CT_DefaultShapeDefinition.html +99 -0
- data/rdoc/RubyXL/CT_DuotoneEffect.html +99 -0
- data/rdoc/RubyXL/CT_EffectContainer.html +99 -0
- data/rdoc/RubyXL/CT_EffectList.html +99 -0
- data/rdoc/RubyXL/CT_EffectReference.html +99 -0
- data/rdoc/RubyXL/CT_EffectStyleItem.html +99 -0
- data/rdoc/RubyXL/CT_EffectStyleList.html +99 -0
- data/rdoc/RubyXL/CT_EmbeddedWAVAudioFile.html +99 -0
- data/rdoc/RubyXL/CT_FillEffect.html +99 -0
- data/rdoc/RubyXL/CT_FillOverlayEffect.html +99 -0
- data/rdoc/RubyXL/CT_FillStyleList.html +99 -0
- data/rdoc/RubyXL/CT_FlatText.html +99 -0
- data/rdoc/RubyXL/CT_FontCollection.html +99 -0
- data/rdoc/RubyXL/CT_FontReference.html +99 -0
- data/rdoc/RubyXL/CT_GeomGuideList.html +99 -0
- data/rdoc/RubyXL/CT_GlowEffect.html +99 -0
- data/rdoc/RubyXL/CT_GradientFillProperties.html +99 -0
- data/rdoc/RubyXL/CT_GradientStop.html +99 -0
- data/rdoc/RubyXL/CT_GradientStopList.html +99 -0
- data/rdoc/RubyXL/CT_HSLEffect.html +99 -0
- data/rdoc/RubyXL/CT_HslColor.html +99 -0
- data/rdoc/RubyXL/CT_Hyperlink.html +99 -0
- data/rdoc/RubyXL/CT_InnerShadowEffect.html +99 -0
- data/rdoc/RubyXL/CT_LightRig.html +99 -0
- data/rdoc/RubyXL/CT_LineEndProperties.html +99 -0
- data/rdoc/RubyXL/CT_LineJoinMiterProperties.html +99 -0
- data/rdoc/RubyXL/CT_LineProperties.html +99 -0
- data/rdoc/RubyXL/CT_LineStyleList.html +99 -0
- data/rdoc/RubyXL/CT_LinearShadeProperties.html +99 -0
- data/rdoc/RubyXL/CT_LuminanceEffect.html +99 -0
- data/rdoc/RubyXL/CT_ObjectStyleDefaults.html +99 -0
- data/rdoc/RubyXL/CT_OuterShadowEffect.html +99 -0
- data/rdoc/RubyXL/CT_Path2D.html +99 -0
- data/rdoc/RubyXL/CT_Path2DArcTo.html +99 -0
- data/rdoc/RubyXL/CT_Path2DCubicBezierTo.html +99 -0
- data/rdoc/RubyXL/CT_Path2DList.html +99 -0
- data/rdoc/RubyXL/CT_Path2DQuadBezierTo.html +99 -0
- data/rdoc/RubyXL/CT_Path2DTo.html +99 -0
- data/rdoc/RubyXL/CT_PathShadeProperties.html +99 -0
- data/rdoc/RubyXL/CT_PatternFillProperties.html +99 -0
- data/rdoc/RubyXL/CT_Point3D.html +99 -0
- data/rdoc/RubyXL/CT_PolarAdjustHandle.html +99 -0
- data/rdoc/RubyXL/CT_PresetColor.html +99 -0
- data/rdoc/RubyXL/CT_PresetLineDashProperties.html +99 -0
- data/rdoc/RubyXL/CT_PresetShadowEffect.html +99 -0
- data/rdoc/RubyXL/CT_PresetTextShape.html +99 -0
- data/rdoc/RubyXL/CT_ReflectionEffect.html +99 -0
- data/rdoc/RubyXL/CT_RelativeOffsetEffect.html +99 -0
- data/rdoc/RubyXL/CT_RelativeRect.html +99 -0
- data/rdoc/RubyXL/CT_SRgbColor.html +99 -0
- data/rdoc/RubyXL/CT_ScRgbColor.html +99 -0
- data/rdoc/RubyXL/CT_Scene3D.html +99 -0
- data/rdoc/RubyXL/CT_SchemeColor.html +99 -0
- data/rdoc/RubyXL/CT_Shape3D.html +99 -0
- data/rdoc/RubyXL/CT_ShapeStyle.html +99 -0
- data/rdoc/RubyXL/CT_SoftEdgesEffect.html +99 -0
- data/rdoc/RubyXL/CT_SphereCoords.html +99 -0
- data/rdoc/RubyXL/CT_StretchInfoProperties.html +99 -0
- data/rdoc/RubyXL/CT_StyleMatrix.html +99 -0
- data/rdoc/RubyXL/CT_StyleMatrixReference.html +99 -0
- data/rdoc/RubyXL/CT_SupplementalFont.html +99 -0
- data/rdoc/RubyXL/CT_SystemColor.html +99 -0
- data/rdoc/RubyXL/CT_TextAutonumberBullet.html +99 -0
- data/rdoc/RubyXL/CT_TextBlipBullet.html +99 -0
- data/rdoc/RubyXL/CT_TextCharBullet.html +99 -0
- data/rdoc/RubyXL/CT_TextCharacterProperties.html +99 -0
- data/rdoc/RubyXL/CT_TextFont.html +99 -0
- data/rdoc/RubyXL/CT_TextListStyle.html +99 -0
- data/rdoc/RubyXL/CT_TextNormalAutofit.html +99 -0
- data/rdoc/RubyXL/CT_TextParagraphProperties.html +99 -0
- data/rdoc/RubyXL/CT_TextSpacing.html +99 -0
- data/rdoc/RubyXL/CT_TextTabStop.html +99 -0
- data/rdoc/RubyXL/CT_TextTabStopList.html +99 -0
- data/rdoc/RubyXL/CT_TileInfoProperties.html +99 -0
- data/rdoc/RubyXL/CT_TintEffect.html +99 -0
- data/rdoc/RubyXL/CT_Transform2D.html +99 -0
- data/rdoc/RubyXL/CT_TransformEffect.html +99 -0
- data/rdoc/RubyXL/CT_Vector3D.html +99 -0
- data/rdoc/RubyXL/CT_XYAdjustHandle.html +99 -0
- data/rdoc/RubyXL/CalculationChain.html +149 -0
- data/rdoc/RubyXL/CalculationChainCell.html +99 -0
- data/rdoc/RubyXL/CalculationProperties.html +99 -0
- data/rdoc/RubyXL/Cell.html +510 -0
- data/rdoc/RubyXL/CellConvenienceMethods.html +1077 -0
- data/rdoc/RubyXL/CellExt.html +99 -0
- data/rdoc/RubyXL/CellSmartTag.html +99 -0
- data/rdoc/RubyXL/CellSmartTagProperty.html +99 -0
- data/rdoc/RubyXL/CellSmartTags.html +99 -0
- data/rdoc/RubyXL/CellStyle.html +99 -0
- data/rdoc/RubyXL/CellStyleXFs.html +138 -0
- data/rdoc/RubyXL/CellStyles.html +138 -0
- data/rdoc/RubyXL/CellValue.html +139 -0
- data/rdoc/RubyXL/CellWatch.html +99 -0
- data/rdoc/RubyXL/CellWatches.html +99 -0
- data/rdoc/RubyXL/CellXFs.html +139 -0
- data/rdoc/RubyXL/ChartColorsFile.html +108 -0
- data/rdoc/RubyXL/ChartFile.html +160 -0
- data/rdoc/RubyXL/ChartStyleFile.html +108 -0
- data/rdoc/RubyXL/ChartUserShapesFile.html +108 -0
- data/rdoc/RubyXL/Chartsheet.html +213 -0
- data/rdoc/RubyXL/ChartsheetPageSetup.html +99 -0
- data/rdoc/RubyXL/ChartsheetProperties.html +99 -0
- data/rdoc/RubyXL/ChartsheetProtection.html +99 -0
- data/rdoc/RubyXL/ChartsheetView.html +99 -0
- data/rdoc/RubyXL/ChartsheetViews.html +99 -0
- data/rdoc/RubyXL/Color.html +151 -0
- data/rdoc/RubyXL/ColorConvenienceClasses/HlsColor.html +246 -0
- data/rdoc/RubyXL/ColorConvenienceClasses/RgbColor.html +285 -0
- data/rdoc/RubyXL/ColorConvenienceClasses.html +91 -0
- data/rdoc/RubyXL/ColorConvenienceMethods.html +139 -0
- data/rdoc/RubyXL/ColorFilter.html +99 -0
- data/rdoc/RubyXL/ColorScale.html +99 -0
- data/rdoc/RubyXL/ColorSet.html +99 -0
- data/rdoc/RubyXL/Colors.html +99 -0
- data/rdoc/RubyXL/ColumnRange.html +230 -0
- data/rdoc/RubyXL/ColumnRanges.html +237 -0
- data/rdoc/RubyXL/Comment.html +99 -0
- data/rdoc/RubyXL/CommentList.html +99 -0
- data/rdoc/RubyXL/CommentsFile.html +165 -0
- data/rdoc/RubyXL/ConditionalFormatValue.html +99 -0
- data/rdoc/RubyXL/ConditionalFormatting.html +99 -0
- data/rdoc/RubyXL/ConditionalFormattingRule.html +99 -0
- data/rdoc/RubyXL/Connection.html +99 -0
- data/rdoc/RubyXL/ConnectionTable.html +99 -0
- data/rdoc/RubyXL/ConnectionTables.html +99 -0
- data/rdoc/RubyXL/ConnectionTextField.html +99 -0
- data/rdoc/RubyXL/ConnectionTextFields.html +99 -0
- data/rdoc/RubyXL/Connections.html +149 -0
- data/rdoc/RubyXL/ContentTypeDefault.html +97 -0
- data/rdoc/RubyXL/ContentTypeOverride.html +97 -0
- data/rdoc/RubyXL/ContentTypes.html +211 -0
- data/rdoc/RubyXL/ControlPropertiesFile.html +108 -0
- data/rdoc/RubyXL/CorePropertiesFile.html +355 -0
- data/rdoc/RubyXL/CustomColor.html +99 -0
- data/rdoc/RubyXL/CustomColorList.html +99 -0
- data/rdoc/RubyXL/CustomFilter.html +99 -0
- data/rdoc/RubyXL/CustomFilters.html +99 -0
- data/rdoc/RubyXL/CustomGeometry.html +99 -0
- data/rdoc/RubyXL/CustomProperties.html +99 -0
- data/rdoc/RubyXL/CustomPropertiesFile.html +108 -0
- data/rdoc/RubyXL/CustomProperty.html +99 -0
- data/rdoc/RubyXL/CustomPropertyFile.html +108 -0
- data/rdoc/RubyXL/CustomSheetView.html +99 -0
- data/rdoc/RubyXL/CustomSheetViews.html +99 -0
- data/rdoc/RubyXL/CustomWorkbookView.html +99 -0
- data/rdoc/RubyXL/CustomWorkbookViews.html +99 -0
- data/rdoc/RubyXL/CustomXMLFile.html +106 -0
- data/rdoc/RubyXL/DXF.html +99 -0
- data/rdoc/RubyXL/DXFs.html +99 -0
- data/rdoc/RubyXL/DataBar.html +99 -0
- data/rdoc/RubyXL/DataConsolidate.html +99 -0
- data/rdoc/RubyXL/DataConsolidationReference.html +99 -0
- data/rdoc/RubyXL/DataConsolidationReferences.html +99 -0
- data/rdoc/RubyXL/DataType.html +114 -0
- data/rdoc/RubyXL/DataValidation.html +99 -0
- data/rdoc/RubyXL/DataValidations.html +99 -0
- data/rdoc/RubyXL/DateGroupItem.html +99 -0
- data/rdoc/RubyXL/DefinedName.html +99 -0
- data/rdoc/RubyXL/DefinedNameExt.html +99 -0
- data/rdoc/RubyXL/DefinedNames.html +99 -0
- data/rdoc/RubyXL/DefinedNamesExt.html +99 -0
- data/rdoc/RubyXL/DocumentPropertiesFile.html +213 -0
- data/rdoc/RubyXL/DrawingFile.html +159 -0
- data/rdoc/RubyXL/DynamicFilter.html +99 -0
- data/rdoc/RubyXL/EmbeddedControl.html +99 -0
- data/rdoc/RubyXL/EmbeddedControls.html +99 -0
- data/rdoc/RubyXL/Extension.html +99 -0
- data/rdoc/RubyXL/ExtensionStorageArea.html +99 -0
- data/rdoc/RubyXL/Extents.html +99 -0
- data/rdoc/RubyXL/ExternalBook.html +99 -0
- data/rdoc/RubyXL/ExternalLinksFile.html +155 -0
- data/rdoc/RubyXL/ExternalReference.html +99 -0
- data/rdoc/RubyXL/ExternalReferences.html +99 -0
- data/rdoc/RubyXL/ExtraColorSchemeList.html +99 -0
- data/rdoc/RubyXL/FieldItem.html +99 -0
- data/rdoc/RubyXL/FileRecoveryProperties.html +99 -0
- data/rdoc/RubyXL/FileSharing.html +99 -0
- data/rdoc/RubyXL/FileVersion.html +99 -0
- data/rdoc/RubyXL/Fill.html +138 -0
- data/rdoc/RubyXL/Fills.html +138 -0
- data/rdoc/RubyXL/FilterContainer.html +99 -0
- data/rdoc/RubyXL/FloatNode.html +97 -0
- data/rdoc/RubyXL/FloatValue.html +97 -0
- data/rdoc/RubyXL/Font.html +148 -0
- data/rdoc/RubyXL/FontConvenienceMethods.html +442 -0
- data/rdoc/RubyXL/FontScheme.html +99 -0
- data/rdoc/RubyXL/Fonts.html +138 -0
- data/rdoc/RubyXL/Formula.html +99 -0
- data/rdoc/RubyXL/FunctionGroup.html +99 -0
- data/rdoc/RubyXL/FunctionGroups.html +99 -0
- data/rdoc/RubyXL/GenericStorageObject.html +241 -0
- data/rdoc/RubyXL/GradientFill.html +99 -0
- data/rdoc/RubyXL/HeaderFooterSettings.html +99 -0
- data/rdoc/RubyXL/Hyperlink.html +99 -0
- data/rdoc/RubyXL/HyperlinkRelFile.html +106 -0
- data/rdoc/RubyXL/Hyperlinks.html +99 -0
- data/rdoc/RubyXL/IconFilter.html +99 -0
- data/rdoc/RubyXL/IconSet.html +99 -0
- data/rdoc/RubyXL/IgnoredError.html +99 -0
- data/rdoc/RubyXL/IgnoredErrors.html +99 -0
- data/rdoc/RubyXL/IndexedColors.html +99 -0
- data/rdoc/RubyXL/InputCells.html +99 -0
- data/rdoc/RubyXL/IntegerNode.html +97 -0
- data/rdoc/RubyXL/IntegerValue.html +97 -0
- data/rdoc/RubyXL/LegacyCell.html +130 -0
- data/rdoc/RubyXL/LegacyWorksheet.html +306 -0
- data/rdoc/RubyXL/MRUColors.html +99 -0
- data/rdoc/RubyXL/MacrosFile.html +108 -0
- data/rdoc/RubyXL/MergedCell.html +99 -0
- data/rdoc/RubyXL/MergedCells.html +99 -0
- data/rdoc/RubyXL/NumFmt.html +99 -0
- data/rdoc/RubyXL/NumberFormat.html +139 -0
- data/rdoc/RubyXL/NumberFormats.html +147 -0
- data/rdoc/RubyXL/OLEObject.html +99 -0
- data/rdoc/RubyXL/OLEObjectFile.html +108 -0
- data/rdoc/RubyXL/OLEObjects.html +99 -0
- data/rdoc/RubyXL/OLESize.html +99 -0
- data/rdoc/RubyXL/OOXMLContainerObject.html +309 -0
- data/rdoc/RubyXL/OOXMLIgnored.html +167 -0
- data/rdoc/RubyXL/OOXMLObject.html +107 -0
- data/rdoc/RubyXL/OOXMLObjectClassMethods.html +455 -0
- data/rdoc/RubyXL/OOXMLObjectInstanceMethods.html +442 -0
- data/rdoc/RubyXL/OOXMLRelationshipsFile.html +470 -0
- data/rdoc/RubyXL/OOXMLTopLevelObject.html +297 -0
- data/rdoc/RubyXL/OdbcOleDbProperties.html +99 -0
- data/rdoc/RubyXL/Offset.html +99 -0
- data/rdoc/RubyXL/OlapProperties.html +99 -0
- data/rdoc/RubyXL/OleItem.html +99 -0
- data/rdoc/RubyXL/OleItems.html +99 -0
- data/rdoc/RubyXL/OleLink.html +99 -0
- data/rdoc/RubyXL/OutlineProperties.html +99 -0
- data/rdoc/RubyXL/PageMargins.html +99 -0
- data/rdoc/RubyXL/PageSetup.html +99 -0
- data/rdoc/RubyXL/PageSetupProperties.html +99 -0
- data/rdoc/RubyXL/Pane.html +99 -0
- data/rdoc/RubyXL/Parser.html +174 -0
- data/rdoc/RubyXL/PatternFill.html +99 -0
- data/rdoc/RubyXL/PersonMetadata.html +108 -0
- data/rdoc/RubyXL/PhoneticProperties.html +99 -0
- data/rdoc/RubyXL/PhoneticRun.html +99 -0
- data/rdoc/RubyXL/PivotArea.html +99 -0
- data/rdoc/RubyXL/PivotCache.html +99 -0
- data/rdoc/RubyXL/PivotCacheDefinitionFile.html +116 -0
- data/rdoc/RubyXL/PivotCacheRecordsFile.html +108 -0
- data/rdoc/RubyXL/PivotCaches.html +99 -0
- data/rdoc/RubyXL/PivotReference.html +99 -0
- data/rdoc/RubyXL/PivotReferences.html +99 -0
- data/rdoc/RubyXL/PivotTableFile.html +116 -0
- data/rdoc/RubyXL/PivotTableSelection.html +99 -0
- data/rdoc/RubyXL/PresetGeometry.html +99 -0
- data/rdoc/RubyXL/PrintOptions.html +99 -0
- data/rdoc/RubyXL/PrinterSettingsFile.html +108 -0
- data/rdoc/RubyXL/ProtectedRange.html +99 -0
- data/rdoc/RubyXL/ProtectedRanges.html +99 -0
- data/rdoc/RubyXL/Protection.html +99 -0
- data/rdoc/RubyXL/QueryParameter.html +99 -0
- data/rdoc/RubyXL/QueryParameters.html +99 -0
- data/rdoc/RubyXL/QueryTable.html +157 -0
- data/rdoc/RubyXL/QueryTableDeletedField.html +99 -0
- data/rdoc/RubyXL/QueryTableDeletedFields.html +99 -0
- data/rdoc/RubyXL/QueryTableField.html +99 -0
- data/rdoc/RubyXL/QueryTableFields.html +99 -0
- data/rdoc/RubyXL/QueryTableRefresh.html +99 -0
- data/rdoc/RubyXL/RID.html +97 -0
- data/rdoc/RubyXL/RawOOXML.html +187 -0
- data/rdoc/RubyXL/Reference.html +510 -0
- data/rdoc/RubyXL/Relationship.html +97 -0
- data/rdoc/RubyXL/RelationshipSupport/ClassMehods.html +131 -0
- data/rdoc/RubyXL/RelationshipSupport.html +336 -0
- data/rdoc/RubyXL/RevisionPointer.html +99 -0
- data/rdoc/RubyXL/RichText.html +141 -0
- data/rdoc/RubyXL/RichTextRun.html +138 -0
- data/rdoc/RubyXL/Row.html +357 -0
- data/rdoc/RubyXL/RowExt.html +99 -0
- data/rdoc/RubyXL/RunProperties.html +99 -0
- data/rdoc/RubyXL/Scenario.html +99 -0
- data/rdoc/RubyXL/Scenarios.html +99 -0
- data/rdoc/RubyXL/Selection.html +146 -0
- data/rdoc/RubyXL/ShapeGuide.html +99 -0
- data/rdoc/RubyXL/ShapeTextRectangle.html +99 -0
- data/rdoc/RubyXL/SharedStringsTable.html +328 -0
- data/rdoc/RubyXL/Sheet.html +99 -0
- data/rdoc/RubyXL/SheetCalculationProperties.html +99 -0
- data/rdoc/RubyXL/SheetData.html +162 -0
- data/rdoc/RubyXL/SheetDataExt.html +99 -0
- data/rdoc/RubyXL/SheetDataSet.html +99 -0
- data/rdoc/RubyXL/SheetMetadata.html +108 -0
- data/rdoc/RubyXL/SheetName.html +99 -0
- data/rdoc/RubyXL/SheetNames.html +99 -0
- data/rdoc/RubyXL/Sheets.html +99 -0
- data/rdoc/RubyXL/SlicerCacheFile.html +108 -0
- data/rdoc/RubyXL/SlicerFile.html +108 -0
- data/rdoc/RubyXL/SmartTagProperties.html +99 -0
- data/rdoc/RubyXL/SmartTagType.html +99 -0
- data/rdoc/RubyXL/SmartTagTypes.html +99 -0
- data/rdoc/RubyXL/SmartTags.html +99 -0
- data/rdoc/RubyXL/SortCondition.html +99 -0
- data/rdoc/RubyXL/SortState.html +99 -0
- data/rdoc/RubyXL/Sqref.html +167 -0
- data/rdoc/RubyXL/Stop.html +99 -0
- data/rdoc/RubyXL/StringNode.html +97 -0
- data/rdoc/RubyXL/StringNodeW3C.html +167 -0
- data/rdoc/RubyXL/StringValue.html +97 -0
- data/rdoc/RubyXL/Stylesheet.html +281 -0
- data/rdoc/RubyXL/TableFile.html +108 -0
- data/rdoc/RubyXL/TableParts.html +97 -0
- data/rdoc/RubyXL/TableStyle.html +99 -0
- data/rdoc/RubyXL/TableStyles.html +99 -0
- data/rdoc/RubyXL/Text.html +175 -0
- data/rdoc/RubyXL/TextImportSettings.html +99 -0
- data/rdoc/RubyXL/Theme.html +535 -0
- data/rdoc/RubyXL/ThemeElements.html +99 -0
- data/rdoc/RubyXL/ThumbnailFile.html +108 -0
- data/rdoc/RubyXL/Top10.html +99 -0
- data/rdoc/RubyXL/VMLDrawingFile.html +116 -0
- data/rdoc/RubyXL/Variant.html +99 -0
- data/rdoc/RubyXL/Vector.html +142 -0
- data/rdoc/RubyXL/VectorValue.html +97 -0
- data/rdoc/RubyXL/VisualProperties.html +99 -0
- data/rdoc/RubyXL/WebPublishObject.html +99 -0
- data/rdoc/RubyXL/WebPublishObjects.html +99 -0
- data/rdoc/RubyXL/WebPublishingItem.html +99 -0
- data/rdoc/RubyXL/WebPublishingItems.html +99 -0
- data/rdoc/RubyXL/WebPublishingProperties.html +99 -0
- data/rdoc/RubyXL/WebQueryProperties.html +99 -0
- data/rdoc/RubyXL/Workbook.html +948 -0
- data/rdoc/RubyXL/WorkbookConvenienceMethods.html +596 -0
- data/rdoc/RubyXL/WorkbookProperties.html +99 -0
- data/rdoc/RubyXL/WorkbookProtection.html +99 -0
- data/rdoc/RubyXL/WorkbookRoot.html +325 -0
- data/rdoc/RubyXL/WorkbookView.html +99 -0
- data/rdoc/RubyXL/WorkbookViews.html +99 -0
- data/rdoc/RubyXL/Worksheet.html +418 -0
- data/rdoc/RubyXL/WorksheetConvenienceMethods.html +2205 -0
- data/rdoc/RubyXL/WorksheetDimensions.html +99 -0
- data/rdoc/RubyXL/WorksheetFormatProperties.html +97 -0
- data/rdoc/RubyXL/WorksheetProperties.html +99 -0
- data/rdoc/RubyXL/WorksheetProtection.html +99 -0
- data/rdoc/RubyXL/WorksheetView.html +99 -0
- data/rdoc/RubyXL/WorksheetViews.html +99 -0
- data/rdoc/RubyXL/XF.html +99 -0
- data/rdoc/RubyXL.html +338 -0
- data/rdoc/created.rid +45 -0
- data/rdoc/css/fonts.css +167 -0
- data/rdoc/css/rdoc.css +687 -0
- data/rdoc/fonts/Lato-Light.ttf +0 -0
- data/rdoc/fonts/Lato-LightItalic.ttf +0 -0
- data/rdoc/fonts/Lato-Regular.ttf +0 -0
- data/rdoc/fonts/Lato-RegularItalic.ttf +0 -0
- data/rdoc/fonts/SourceCodePro-Bold.ttf +0 -0
- data/rdoc/fonts/SourceCodePro-Regular.ttf +0 -0
- data/rdoc/images/add.png +0 -0
- data/rdoc/images/arrow_up.png +0 -0
- data/rdoc/images/brick.png +0 -0
- data/rdoc/images/brick_link.png +0 -0
- data/rdoc/images/bug.png +0 -0
- data/rdoc/images/bullet_black.png +0 -0
- data/rdoc/images/bullet_toggle_minus.png +0 -0
- data/rdoc/images/bullet_toggle_plus.png +0 -0
- data/rdoc/images/date.png +0 -0
- data/rdoc/images/delete.png +0 -0
- data/rdoc/images/find.png +0 -0
- data/rdoc/images/loadingAnimation.gif +0 -0
- data/rdoc/images/macFFBgHack.png +0 -0
- data/rdoc/images/package.png +0 -0
- data/rdoc/images/page_green.png +0 -0
- data/rdoc/images/page_white_text.png +0 -0
- data/rdoc/images/page_white_width.png +0 -0
- data/rdoc/images/plugin.png +0 -0
- data/rdoc/images/ruby.png +0 -0
- data/rdoc/images/tag_blue.png +0 -0
- data/rdoc/images/tag_green.png +0 -0
- data/rdoc/images/transparent.png +0 -0
- data/rdoc/images/wrench.png +0 -0
- data/rdoc/images/wrench_orange.png +0 -0
- data/rdoc/images/zoom.png +0 -0
- data/rdoc/index.html +477 -0
- data/rdoc/js/darkfish.js +97 -0
- data/rdoc/js/navigation.js +105 -0
- data/rdoc/js/navigation.js.gz +0 -0
- data/rdoc/js/search.js +110 -0
- data/rdoc/js/search_index.js +1 -0
- data/rdoc/js/search_index.js.gz +0 -0
- data/rdoc/js/searcher.js +229 -0
- data/rdoc/js/searcher.js.gz +0 -0
- data/rdoc/table_of_contents.html +3021 -0
- data/rubyXL.gemspec +521 -60
- data/spec/lib/cell_spec.rb +386 -143
- data/spec/lib/color_spec.rb +11 -4
- data/spec/lib/parser_spec.rb +90 -38
- data/spec/lib/reference_spec.rb +64 -0
- data/spec/lib/rgb_color_spec.rb +29 -0
- data/spec/lib/stylesheet_spec.rb +27 -0
- data/spec/lib/text_spec.rb +27 -0
- data/spec/lib/workbook_spec.rb +168 -22
- data/spec/lib/worksheet_spec.rb +1207 -1220
- data/spec/spec_helper.rb +13 -0
- data/test/input/.gitkeep +0 -0
- data/test/output/.gitkeep +0 -0
- data/test/test_parse_write.rb +15 -0
- data/tmp/.gitignore +1 -0
- metadata +634 -168
- data/Gemfile.lock +0 -34
- data/lib/.DS_Store +0 -0
- data/lib/rubyXL/Hash.rb +0 -60
- data/lib/rubyXL/color.rb +0 -14
- data/lib/rubyXL/private_class.rb +0 -265
- data/lib/rubyXL/workbook.rb +0 -450
- data/lib/rubyXL/writer/app_writer.rb +0 -62
- data/lib/rubyXL/writer/calc_chain_writer.rb +0 -33
- data/lib/rubyXL/writer/content_types_writer.rb +0 -77
- data/lib/rubyXL/writer/core_writer.rb +0 -51
- data/lib/rubyXL/writer/root_rels_writer.rb +0 -25
- data/lib/rubyXL/writer/shared_strings_writer.rb +0 -30
- data/lib/rubyXL/writer/styles_writer.rb +0 -407
- data/lib/rubyXL/writer/theme_writer.rb +0 -343
- data/lib/rubyXL/writer/workbook_rels_writer.rb +0 -59
- data/lib/rubyXL/writer/workbook_writer.rb +0 -77
- data/lib/rubyXL/writer/worksheet_writer.rb +0 -230
- data/lib/rubyXL/zip.rb +0 -20
- data/spec/lib/hash_spec.rb +0 -28
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'rubyXL/objects/ooxml_object'
|
2
|
+
require 'rubyXL/objects/simple_types'
|
3
|
+
require 'rubyXL/objects/extensions'
|
4
|
+
|
5
|
+
module RubyXL
|
6
|
+
# http://www.datypic.com/sc/ooxml/e-ssml_dateGroupItem-1.html
|
7
|
+
class DateGroupItem < OOXMLObject
|
8
|
+
define_attribute(:year, :int, :required => true)
|
9
|
+
define_attribute(:month, :int)
|
10
|
+
define_attribute(:day, :int)
|
11
|
+
define_attribute(:hour, :int)
|
12
|
+
define_attribute(:minute, :int)
|
13
|
+
define_attribute(:second, :int)
|
14
|
+
define_attribute(:dateTimeGrouping, RubyXL::ST_DateTimeGrouping)
|
15
|
+
define_element_name 'dateGroupItem'
|
16
|
+
end
|
17
|
+
|
18
|
+
# http://www.datypic.com/sc/ooxml/e-ssml_filters-1.html
|
19
|
+
class FilterContainer < OOXMLObject
|
20
|
+
define_attribute(:blank, :bool, :default => false)
|
21
|
+
define_attribute(:calendarType, RubyXL::ST_CalendarType, :default => 'none')
|
22
|
+
define_child_node(RubyXL::StringValue, :collection => true, :accessor => :filters, :node_name => :filter)
|
23
|
+
define_child_node(RubyXL::DateGroupItem, :collection => true, :accessor => :date_group_items)
|
24
|
+
define_element_name 'filters'
|
25
|
+
end
|
26
|
+
|
27
|
+
# http://www.datypic.com/sc/ooxml/e-ssml_top10-1.html
|
28
|
+
class Top10 < OOXMLObject
|
29
|
+
define_attribute(:top, :bool, :default => true)
|
30
|
+
define_attribute(:percent, :bool, :default => false)
|
31
|
+
define_attribute(:val, :double, :required => true)
|
32
|
+
define_attribute(:filterVal, :double)
|
33
|
+
define_element_name 'top10'
|
34
|
+
end
|
35
|
+
|
36
|
+
# http://www.datypic.com/sc/ooxml/e-ssml_customFilter-1.html
|
37
|
+
class CustomFilter < OOXMLObject
|
38
|
+
define_attribute(:operator, RubyXL::ST_FilterOperator, :default => 'equal')
|
39
|
+
define_attribute(:val, :string)
|
40
|
+
define_element_name 'customFilter'
|
41
|
+
end
|
42
|
+
|
43
|
+
# http://www.datypic.com/sc/ooxml/e-ssml_customFilters-1.html
|
44
|
+
class CustomFilters < OOXMLContainerObject
|
45
|
+
define_attribute(:and, :bool, :default => false)
|
46
|
+
define_child_node(RubyXL::CustomFilter, :collection => true)
|
47
|
+
define_element_name 'customFilters'
|
48
|
+
end
|
49
|
+
|
50
|
+
# http://www.datypic.com/sc/ooxml/e-ssml_dynamicFilter-1.html
|
51
|
+
class DynamicFilter < OOXMLObject
|
52
|
+
define_attribute(:type, RubyXL::ST_DynamicFilterType, :required => true)
|
53
|
+
define_attribute(:val, :double)
|
54
|
+
define_attribute(:maxVal, :double)
|
55
|
+
define_element_name 'dynamicFilter'
|
56
|
+
end
|
57
|
+
|
58
|
+
# http://www.datypic.com/sc/ooxml/e-ssml_colorFilter-1.html
|
59
|
+
class ColorFilter < OOXMLObject
|
60
|
+
define_attribute(:dxfId, :string)
|
61
|
+
define_attribute(:cellColor, :bool)
|
62
|
+
define_element_name 'colorFilter'
|
63
|
+
end
|
64
|
+
|
65
|
+
# http://www.datypic.com/sc/ooxml/e-ssml_iconFilter-1.html
|
66
|
+
class IconFilter < OOXMLObject
|
67
|
+
define_attribute(:iconSet, RubyXL::ST_IconSetType)
|
68
|
+
define_attribute(:iconId, :int)
|
69
|
+
define_element_name 'iconFilter'
|
70
|
+
end
|
71
|
+
|
72
|
+
# http://www.datypic.com/sc/ooxml/e-ssml_filterColumn-1.html
|
73
|
+
class AutoFilterColumn < OOXMLObject
|
74
|
+
define_attribute(:colId, :int, :required => true)
|
75
|
+
define_attribute(:hiddenButton, :bool, :default => false)
|
76
|
+
define_attribute(:showButton, :bool, :default => true)
|
77
|
+
define_child_node(RubyXL::FilterContainer)
|
78
|
+
define_child_node(RubyXL::Top10)
|
79
|
+
define_child_node(RubyXL::CustomFilters)
|
80
|
+
define_child_node(RubyXL::DynamicFilter)
|
81
|
+
define_child_node(RubyXL::ColorFilter)
|
82
|
+
define_child_node(RubyXL::IconFilter)
|
83
|
+
define_child_node(RubyXL::ExtensionStorageArea)
|
84
|
+
define_element_name 'filterColumn'
|
85
|
+
end
|
86
|
+
|
87
|
+
# http://www.datypic.com/sc/ooxml/e-ssml_sortCondition-1.html
|
88
|
+
class SortCondition < OOXMLObject
|
89
|
+
define_attribute(:descending, :bool, :default => false)
|
90
|
+
define_attribute(:sortBy, RubyXL::ST_SortBy, :default => 'value')
|
91
|
+
define_attribute(:ref, :ref, :required => true)
|
92
|
+
define_attribute(:customList, :string)
|
93
|
+
define_attribute(:dxfId, :int)
|
94
|
+
define_attribute(:iconSet, RubyXL::ST_IconSetType, :required => true, :default => '3Arrows')
|
95
|
+
define_attribute(:iconId, :int)
|
96
|
+
define_element_name 'sortCondition'
|
97
|
+
end
|
98
|
+
|
99
|
+
# http://www.datypic.com/sc/ooxml/e-ssml_sortState-2.html
|
100
|
+
class SortState < OOXMLObject
|
101
|
+
define_attribute(:columnSort, :bool, :default => false)
|
102
|
+
define_attribute(:caseSensitive, :bool, :default => false)
|
103
|
+
define_attribute(:sortMethod, RubyXL::ST_SortMethod, :default => 'none')
|
104
|
+
define_attribute(:ref, :ref, :required => true)
|
105
|
+
define_child_node(RubyXL::SortCondition, :collection => true)
|
106
|
+
define_child_node(RubyXL::ExtensionStorageArea)
|
107
|
+
define_element_name 'sortState'
|
108
|
+
end
|
109
|
+
|
110
|
+
# http://www.datypic.com/sc/ooxml/e-ssml_autoFilter-2.html
|
111
|
+
class AutoFilter < OOXMLObject
|
112
|
+
define_attribute(:ref, :ref)
|
113
|
+
define_child_node(RubyXL::AutoFilterColumn)
|
114
|
+
define_child_node(RubyXL::SortState)
|
115
|
+
define_child_node(RubyXL::ExtensionStorageArea)
|
116
|
+
define_element_name 'autoFilter'
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rubyXL/objects/ooxml_object'
|
2
|
+
require 'rubyXL/objects/container_nodes'
|
3
|
+
require 'rubyXL/objects/color'
|
4
|
+
|
5
|
+
module RubyXL
|
6
|
+
# http://www.datypic.com/sc/ooxml/e-ssml_font-1.html
|
7
|
+
class Font < OOXMLObject
|
8
|
+
# Since we have no capability to load the actual fonts, we'll have to live with the default.
|
9
|
+
MAX_DIGIT_WIDTH = 7 # Calibri 11 pt @ 96 dpi
|
10
|
+
|
11
|
+
define_child_node(RubyXL::StringValue, :node_name => :name)
|
12
|
+
define_child_node(RubyXL::IntegerValue, :node_name => :charset)
|
13
|
+
define_child_node(RubyXL::IntegerValue, :node_name => :family)
|
14
|
+
define_child_node(RubyXL::BooleanValue, :node_name => :b)
|
15
|
+
define_child_node(RubyXL::BooleanValue, :node_name => :i)
|
16
|
+
define_child_node(RubyXL::BooleanValue, :node_name => :strike)
|
17
|
+
define_child_node(RubyXL::BooleanValue, :node_name => :outline)
|
18
|
+
define_child_node(RubyXL::BooleanValue, :node_name => :shadow)
|
19
|
+
define_child_node(RubyXL::BooleanValue, :node_name => :condense)
|
20
|
+
define_child_node(RubyXL::BooleanValue, :node_name => :extend)
|
21
|
+
define_child_node(RubyXL::Color)
|
22
|
+
define_child_node(RubyXL::FloatValue, :node_name => :sz)
|
23
|
+
define_child_node(RubyXL::StringValue, :node_name => :u) # ST_UnderlineValues (http://www.datypic.com/sc/ooxml/e-ssml_u-1.html)
|
24
|
+
define_child_node(RubyXL::StringValue, :node_name => :vertAlign)
|
25
|
+
define_child_node(RubyXL::StringValue, :node_name => :scheme)
|
26
|
+
define_element_name 'font'
|
27
|
+
|
28
|
+
def self.default(size = 10)
|
29
|
+
self.new(:name => RubyXL::StringValue.new(:val => 'Verdana'),
|
30
|
+
:sz => RubyXL::FloatValue.new(:val => size))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# http://www.datypic.com/sc/ooxml/e-ssml_fonts-1.html
|
35
|
+
class Fonts < OOXMLContainerObject
|
36
|
+
define_child_node(RubyXL::Font, :collection => :with_count)
|
37
|
+
define_element_name 'fonts'
|
38
|
+
|
39
|
+
def self.default
|
40
|
+
self.new(:_ => [ RubyXL::Font.default(10), RubyXL::Font.default(8) ])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rubyXL/objects/ooxml_object'
|
2
|
+
require 'rubyXL/objects/simple_types'
|
3
|
+
|
4
|
+
module RubyXL
|
5
|
+
# http://www.datypic.com/sc/ooxml/e-ssml_f-1.html
|
6
|
+
class Formula < OOXMLObject
|
7
|
+
define_attribute(:_, :string, :accessor => :expression)
|
8
|
+
define_attribute(:t, RubyXL::ST_CellFormulaType, :default => 'normal')
|
9
|
+
define_attribute(:aca, :bool, :default => false)
|
10
|
+
define_attribute(:ref, :ref)
|
11
|
+
define_attribute(:dt2D, :bool, :default => false)
|
12
|
+
define_attribute(:dtr, :bool, :default => false)
|
13
|
+
define_attribute(:del1, :bool, :default => false)
|
14
|
+
define_attribute(:del2, :bool, :default => false)
|
15
|
+
define_attribute(:r1, :ref)
|
16
|
+
define_attribute(:r2, :ref)
|
17
|
+
define_attribute(:ca, :bool, :default => false)
|
18
|
+
define_attribute(:si, :int)
|
19
|
+
define_attribute(:bx, :bool, :default => false)
|
20
|
+
define_element_name 'f'
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,469 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'pathname'
|
3
|
+
require 'rubyXL/objects/reference'
|
4
|
+
|
5
|
+
module RubyXL
|
6
|
+
module OOXMLObjectClassMethods
|
7
|
+
# Get the value of a [sub]class variable if it exists, or create the respective variable
|
8
|
+
# with the passed-in +default+ (or +{}+, if not specified)
|
9
|
+
#
|
10
|
+
# Throughout this class, we are setting class variables through explicit method calls
|
11
|
+
# rather than by directly addressing the name of the variable because of context issues:
|
12
|
+
# addressing variable by name creates it in the context of defining class, while calling
|
13
|
+
# the setter/getter method addresses it in the context of descendant class,
|
14
|
+
# which is what we need.
|
15
|
+
def obtain_class_variable(var_name, default = nil)
|
16
|
+
self.class_variable_get(var_name)
|
17
|
+
rescue NameError
|
18
|
+
self.class_variable_set(var_name, default || {})
|
19
|
+
end
|
20
|
+
|
21
|
+
# Defines an attribute of OOXML object.
|
22
|
+
# === Parameters
|
23
|
+
# * +attribute_name+ - Name of the element attribute as seen in the source XML. Can be either <tt>"String"</tt> or <tt>:Symbol</tt>
|
24
|
+
# * Special attribute name <tt>'_'</tt> (underscore) denotes the value of the element rather than attribute.
|
25
|
+
# * +attribute_type+ - Specifies the conversion type for the attribute when parsing. Available options are:
|
26
|
+
# * +:int+ - <tt>Integer</tt>
|
27
|
+
# * +:uint+ - Unsigned <tt>Integer</tt>
|
28
|
+
# * +:double+ - <tt>Float</tt></u>
|
29
|
+
# * +:string+ - <tt>String</tt> (no conversion)
|
30
|
+
# * +:sqref+ - RubyXL::Sqref
|
31
|
+
# * +:ref+ - RubyXL::Reference
|
32
|
+
# * +:bool+ - <tt>Boolean</tt> ("1" and "true" convert to +true+, others to +false+)
|
33
|
+
# * one of +simple_types+ - <tt>String</tt>, plus the list of acceptable values is saved for future validation (not used yet).
|
34
|
+
# * +extra_parameters+ - Hash of optional parameters as follows:
|
35
|
+
# * +:accessor+ - Name of the accessor for this attribute to be defined on the object. If not provided, defaults to classidied +attribute_name+.
|
36
|
+
# * +:default+ - Value this attribute defaults to if not explicitly provided.
|
37
|
+
# * +:required+ - Whether this attribute is required when writing XML. If the value of the attrinute is not explicitly provided, +:default+ is written instead.
|
38
|
+
# * +:computed+ - Do not store this attribute on +parse+, but do call the object-provided read accessor on +write_xml+.
|
39
|
+
# ==== Examples
|
40
|
+
# define_attribute(:outline, :bool, :default => true)
|
41
|
+
# A <tt>Boolean</tt> attribute 'outline' with default value +true+ will be accessible by calling +obj.outline+
|
42
|
+
# define_attribute(:uniqueCount, :int)
|
43
|
+
# An <tt>Integer</tt> attribute 'uniqueCount' accessible as +obj.unique_count+
|
44
|
+
# define_attribute(:_, :string, :accessor => :expression)
|
45
|
+
# The value of the element will be accessible as a <tt>String</tt> by calling +obj.expression+
|
46
|
+
# define_attribute(:errorStyle, %w{ stop warning information }, :default => 'stop',)
|
47
|
+
# 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>
|
48
|
+
def define_attribute(attr_name, attr_type, extra_params = nil)
|
49
|
+
attrs = obtain_class_variable(:@@ooxml_attributes)
|
50
|
+
attr_hash = { :attr_type => attr_type }
|
51
|
+
attr_hash.merge!(extra_params) if extra_params
|
52
|
+
attr_hash[:accessor] ||= accessorize(attr_name)
|
53
|
+
attrs[attr_name.to_s] = attr_hash
|
54
|
+
self.send(:attr_accessor, attr_hash[:accessor]) unless attr_hash[:computed]
|
55
|
+
end
|
56
|
+
|
57
|
+
# Defines a `r:id` attribute
|
58
|
+
def define_relationship(extra_params = {})
|
59
|
+
define_attribute(:'r:id', :string, extra_params)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Defines a child node of OOXML object.
|
63
|
+
# === Parameters
|
64
|
+
# * +klass+ - Class (descendant of RubyXL::OOXMLObject) of the child nodes. Child node objects will be produced by calling +parse+ method of that class.
|
65
|
+
# * +extra_parameters+ - Hash of optional parameters as follows:
|
66
|
+
# * +:accessor+ - Name of the accessor for this attribute to be defined on the object. If not provided, defaults to classidied +attribute_name+.
|
67
|
+
# * +:node_name+ - Node name for the child node, in case it does not match the one defined by the +klass+.
|
68
|
+
# * +:collection+ - Whether the child node should be treated as a single node or a collection of nodes:
|
69
|
+
# * +false+ (default) - child node is directly accessible through the respective accessor;
|
70
|
+
# * +true+ - a collection of child nodes is accessed as +Array+ through the respective accessor;
|
71
|
+
# * +:with_count+ - same as +true+, but in addition, the attribute +count+ is defined on the current object, that will be automatically set to the number of elements in the collection at the start of +write_xml+ call.
|
72
|
+
# ==== Examples
|
73
|
+
# define_child_node(RubyXL::Alignment)
|
74
|
+
# Define a singular child node parsed by the RubyXL::BorderEdge.parse() and accessed by the default <tt>obj.alignment</tt> accessor
|
75
|
+
# define_child_node(RubyXL::Hyperlink, :collection => true, :accessor => :hyperlinks)
|
76
|
+
# Define an array of nodes accessed by <tt>obj.hyperlinks</tt> accessor, each of which will be parsed by the RubyXL::Hyperlink.parse()
|
77
|
+
# define_child_node(RubyXL::BorderEdge, :node_name => :left)
|
78
|
+
# define_child_node(RubyXL::BorderEdge, :node_name => :right)
|
79
|
+
# Use class RubyXL::BorderEdge when parsing both the elements <tt><left ...></tt> and <tt><right ...></tt> elements.
|
80
|
+
# define_child_node(RubyXL::Font, :collection => :with_count, :accessor => :fonts)
|
81
|
+
# 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
|
82
|
+
def define_child_node(klass, extra_params = {})
|
83
|
+
child_nodes = obtain_class_variable(:@@ooxml_child_nodes)
|
84
|
+
child_node_name = (extra_params[:node_name] || klass.class_variable_get(:@@ooxml_tag_name)).to_s
|
85
|
+
accessor = (extra_params[:accessor] || accessorize(child_node_name)).to_sym
|
86
|
+
|
87
|
+
child_nodes[child_node_name] = {
|
88
|
+
:class => klass,
|
89
|
+
:is_array => extra_params[:collection],
|
90
|
+
:accessor => accessor
|
91
|
+
}
|
92
|
+
|
93
|
+
define_count_attribute if extra_params[:collection] == :with_count
|
94
|
+
|
95
|
+
self.send(:attr_accessor, accessor)
|
96
|
+
end
|
97
|
+
|
98
|
+
def define_count_attribute
|
99
|
+
define_attribute(:count, :uint, :required => true)
|
100
|
+
end
|
101
|
+
private :define_count_attribute
|
102
|
+
|
103
|
+
# Defines the name of the element that represents the current OOXML object. Should only be used once per object.
|
104
|
+
# In case of different objects represented by the same class in different parts of OOXML tree, +:node_name+
|
105
|
+
# extra parameter can be used to override the default element name.
|
106
|
+
# === Parameters
|
107
|
+
# * +element_name+
|
108
|
+
# ==== Examples
|
109
|
+
# define_element_name 'externalReference'
|
110
|
+
def define_element_name(element_name)
|
111
|
+
self.class_variable_set(:@@ooxml_tag_name, element_name)
|
112
|
+
end
|
113
|
+
|
114
|
+
def parse(node, known_namespaces = nil)
|
115
|
+
case node
|
116
|
+
when String, IO, Zip::InputStream then node = Nokogiri::XML.parse(node)
|
117
|
+
end
|
118
|
+
|
119
|
+
if node.is_a?(Nokogiri::XML::Document) then
|
120
|
+
node = node.root
|
121
|
+
# ignorable_attr = node.attributes['Ignorable']
|
122
|
+
# @ignorables << ignorable_attr.value if ignorable_attr
|
123
|
+
end
|
124
|
+
|
125
|
+
obj = self.new
|
126
|
+
hsh = {}
|
127
|
+
node.namespace_definitions.each { |ns| hsh[ns.href] = ns.prefix }
|
128
|
+
obj.local_namespaces = hsh
|
129
|
+
|
130
|
+
known_attributes = obtain_class_variable(:@@ooxml_attributes)
|
131
|
+
|
132
|
+
content_params = known_attributes['_']
|
133
|
+
process_attribute(obj, node.text, content_params) if content_params
|
134
|
+
|
135
|
+
node.attributes.each_pair { |attr_name, attr|
|
136
|
+
attr_name = if attr.namespace then "#{attr.namespace.prefix}:#{attr.name}"
|
137
|
+
else attr.name
|
138
|
+
end
|
139
|
+
|
140
|
+
attr_params = known_attributes[attr_name]
|
141
|
+
|
142
|
+
next if attr_params.nil?
|
143
|
+
# raise "Unknown attribute [#{attr_name}] for element [#{node.name}]" if attr_params.nil?
|
144
|
+
process_attribute(obj, attr.value, attr_params) unless attr_params[:computed]
|
145
|
+
}
|
146
|
+
|
147
|
+
known_child_nodes = obtain_class_variable(:@@ooxml_child_nodes)
|
148
|
+
|
149
|
+
unless known_child_nodes.empty?
|
150
|
+
known_namespaces ||= obtain_class_variable(:@@ooxml_namespaces)
|
151
|
+
|
152
|
+
node.element_children.each { |child_node|
|
153
|
+
ns = child_node.namespace
|
154
|
+
|
155
|
+
prefix = if known_namespaces.has_key?(ns&.href) then known_namespaces[ns&.href]
|
156
|
+
else ns&.prefix
|
157
|
+
end
|
158
|
+
|
159
|
+
child_node_name = case prefix
|
160
|
+
when '', nil then child_node.name
|
161
|
+
else "#{prefix}:#{child_node.name}"
|
162
|
+
end
|
163
|
+
|
164
|
+
child_node_params = known_child_nodes[child_node_name]
|
165
|
+
raise "Unknown child node [#{child_node_name}] for element [#{node.name}]" if child_node_params.nil?
|
166
|
+
parsed_object = child_node_params[:class].parse(child_node, known_namespaces)
|
167
|
+
if child_node_params[:is_array] then
|
168
|
+
index = parsed_object.index_in_collection
|
169
|
+
|
170
|
+
collection = if (self < RubyXL::OOXMLContainerObject) then obj
|
171
|
+
else obj.send(child_node_params[:accessor])
|
172
|
+
end
|
173
|
+
|
174
|
+
if index.nil? then
|
175
|
+
collection << parsed_object
|
176
|
+
else
|
177
|
+
collection[index] = parsed_object
|
178
|
+
end
|
179
|
+
else
|
180
|
+
obj.send("#{child_node_params[:accessor]}=", parsed_object)
|
181
|
+
end
|
182
|
+
}
|
183
|
+
end
|
184
|
+
|
185
|
+
obj
|
186
|
+
end
|
187
|
+
|
188
|
+
private
|
189
|
+
def accessorize(str)
|
190
|
+
acc = str.to_s.dup
|
191
|
+
acc.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
|
192
|
+
acc.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
|
193
|
+
acc.gsub!(':', '_')
|
194
|
+
acc.downcase.to_sym
|
195
|
+
end
|
196
|
+
|
197
|
+
def process_attribute(obj, raw_value, params)
|
198
|
+
val = raw_value &&
|
199
|
+
case params[:attr_type]
|
200
|
+
when :double then Float(raw_value) # http://www.datypic.com/sc/xsd/t-xsd_double.html
|
201
|
+
when :string then raw_value
|
202
|
+
when Array then raw_value # Case of Simple Types
|
203
|
+
when :sqref then RubyXL::Sqref.new(raw_value)
|
204
|
+
when :ref then RubyXL::Reference.new(raw_value)
|
205
|
+
when :bool then ['1', 'true'].include?(raw_value) # http://www.datypic.com/sc/xsd/t-xsd_boolean.html
|
206
|
+
when :int then Integer(raw_value)
|
207
|
+
when :uint then
|
208
|
+
v = Integer(raw_value)
|
209
|
+
raise ArgumentError.new("invalid value for unsigned Integer(): \"#{raw_value}\"") if v < 0
|
210
|
+
v
|
211
|
+
end
|
212
|
+
obj.send("#{params[:accessor]}=", val)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
|
217
|
+
module OOXMLObjectInstanceMethods
|
218
|
+
attr_accessor :local_namespaces
|
219
|
+
|
220
|
+
def self.included(klass)
|
221
|
+
klass.extend RubyXL::OOXMLObjectClassMethods
|
222
|
+
end
|
223
|
+
|
224
|
+
def obtain_class_variable(var_name, default = {})
|
225
|
+
self.class.obtain_class_variable(var_name, default)
|
226
|
+
end
|
227
|
+
private :obtain_class_variable
|
228
|
+
|
229
|
+
def initialize(params = nil)
|
230
|
+
@local_namespaces = nil
|
231
|
+
params ||= {}
|
232
|
+
|
233
|
+
obtain_class_variable(:@@ooxml_attributes).each_value { |v|
|
234
|
+
instance_variable_set("@#{v[:accessor]}", params[v[:accessor]]) unless v[:computed]
|
235
|
+
}
|
236
|
+
|
237
|
+
init_child_nodes(params)
|
238
|
+
end
|
239
|
+
|
240
|
+
def init_child_nodes(params)
|
241
|
+
obtain_class_variable(:@@ooxml_child_nodes).each_value { |v|
|
242
|
+
initial_value =
|
243
|
+
if params.has_key?(v[:accessor]) then params[v[:accessor]]
|
244
|
+
elsif v[:is_array] then []
|
245
|
+
else nil
|
246
|
+
end
|
247
|
+
|
248
|
+
instance_variable_set("@#{v[:accessor]}", initial_value)
|
249
|
+
}
|
250
|
+
end
|
251
|
+
private :init_child_nodes
|
252
|
+
|
253
|
+
def preserve_whitespace
|
254
|
+
self.xml_space = (value.is_a?(String) && ((value =~ /\A\s/) || (value =~ /\s\Z/) || value.include?("\n"))) ? 'preserve' : nil
|
255
|
+
end
|
256
|
+
private :preserve_whitespace
|
257
|
+
|
258
|
+
def ==(other)
|
259
|
+
other.is_a?(self.class) &&
|
260
|
+
obtain_class_variable(:@@ooxml_attributes).all? { |_k, v| self.send(v[:accessor]) == other.send(v[:accessor]) } &&
|
261
|
+
obtain_class_variable(:@@ooxml_child_nodes).all? { |_k, v| self.send(v[:accessor]) == other.send(v[:accessor]) }
|
262
|
+
end
|
263
|
+
|
264
|
+
# Recursively write the OOXML object and all its children out as Nokogiri::XML. Immediately before the actual
|
265
|
+
# generation, +before_write_xml()+ is called to perform last-minute cleanup and validation operations; if it
|
266
|
+
# returns +false+, an empty string is returned (rather than +nil+, so Nokogiri::XML's <tt><<</tt> operator
|
267
|
+
# can be used without additional +nil+ checking)
|
268
|
+
# === Parameters
|
269
|
+
# * +xml+ - Base Nokogiri::XML object used for building. If omitted, a blank document will be generated.
|
270
|
+
# * +node_name_override+ - if present, is used instead of the default element name for this object provided by +define_element_name+
|
271
|
+
# ==== Examples
|
272
|
+
# obj.write_xml()
|
273
|
+
# Creates a new empty +Nokogiri::XML+, populates it with the OOXML structure as described in the respective definition, and returns the resulting +Nokogiri::XML+ object.
|
274
|
+
# obj.write_xml(seed_xml)
|
275
|
+
# Using the passed-in +Nokogiri+ +xml+ object, creates a new element corresponding to +obj+ according to its definition, along with all its properties and children, and returns the newly created element.
|
276
|
+
# obj.write_xml(seed_xml, 'overriden_element_name')
|
277
|
+
# Same as above, but uses the passed-in +node_name_override+ as the new element name, instead of its default name set by +define_element_name+.
|
278
|
+
def write_xml(xml = nil, node_name_override = nil)
|
279
|
+
if xml.nil? then
|
280
|
+
seed_xml = Nokogiri::XML('<?xml version = "1.0" standalone ="yes"?>')
|
281
|
+
seed_xml.encoding = 'UTF-8'
|
282
|
+
|
283
|
+
if Nokogiri.jruby? then # Issue 188 workaround for JRuby
|
284
|
+
seed_xml.to_java.strict_error_checking = false
|
285
|
+
end
|
286
|
+
|
287
|
+
result = self.write_xml(seed_xml)
|
288
|
+
return result if result == ''
|
289
|
+
seed_xml << result
|
290
|
+
return seed_xml.to_xml({ :indent => 0, :save_with => Nokogiri::XML::Node::SaveOptions::AS_XML })
|
291
|
+
end
|
292
|
+
|
293
|
+
return '' unless before_write_xml
|
294
|
+
|
295
|
+
attrs = {}
|
296
|
+
|
297
|
+
obtain_class_variable(:@@ooxml_attributes).each_pair { |k, v|
|
298
|
+
val = self.send(v[:accessor])
|
299
|
+
|
300
|
+
if val.nil? then
|
301
|
+
next unless v[:required]
|
302
|
+
val = v[:default]
|
303
|
+
end
|
304
|
+
|
305
|
+
val = val &&
|
306
|
+
case v[:attr_type]
|
307
|
+
when :bool then val ? '1' : '0'
|
308
|
+
when :double then val.to_s.gsub(/\.0*\Z/, '') # Trim trailing zeroes
|
309
|
+
else val
|
310
|
+
end
|
311
|
+
|
312
|
+
attrs[k] = val
|
313
|
+
}
|
314
|
+
|
315
|
+
element_text = attrs.delete('_')
|
316
|
+
elem = xml.create_element(node_name_override || obtain_class_variable(:@@ooxml_tag_name), attrs, element_text)
|
317
|
+
|
318
|
+
# First, populate namespaces from the original document
|
319
|
+
@local_namespaces&.each_pair { |href, prefix| elem.add_namespace_definition(prefix, href) }
|
320
|
+
|
321
|
+
# Then, add defaults. Note that if some namespace prefix was already set, Nokogiri will NOT change that namespace.
|
322
|
+
obtain_class_variable(:@@ooxml_namespaces).each_pair { |href, prefix| elem.add_namespace_definition(prefix, href) }
|
323
|
+
|
324
|
+
child_nodes = obtain_class_variable(:@@ooxml_child_nodes)
|
325
|
+
child_nodes.each_pair { |child_node_name, child_node_params|
|
326
|
+
node_obj = get_node_object(child_node_params)
|
327
|
+
next if node_obj.nil?
|
328
|
+
|
329
|
+
if node_obj.respond_to?(:write_xml) && !node_obj.equal?(self) then
|
330
|
+
# If child node is either +OOXMLObject+, or +OOXMLContainerObject+ on its first (envelope) pass,
|
331
|
+
# serialize that object.
|
332
|
+
elem << node_obj.write_xml(xml, child_node_name)
|
333
|
+
else
|
334
|
+
# If child node is either vanilla +Array+, or +OOXMLContainerObject+ on its seconds (content) pass,
|
335
|
+
# serialize its members.
|
336
|
+
node_obj.each { |item| elem << item.write_xml(xml, child_node_name) unless item.nil? }
|
337
|
+
end
|
338
|
+
}
|
339
|
+
elem
|
340
|
+
end
|
341
|
+
|
342
|
+
# Prototype method. For sparse collections (+Rows+, +Cells+, etc.) must return index at which this object
|
343
|
+
# is expected to reside in the collection. If +nil+ is returned, then object is simply added
|
344
|
+
# to the end of the collection.
|
345
|
+
def index_in_collection
|
346
|
+
nil
|
347
|
+
end
|
348
|
+
|
349
|
+
def get_node_object(child_node_params)
|
350
|
+
self.send(child_node_params[:accessor])
|
351
|
+
end
|
352
|
+
private :get_node_object
|
353
|
+
|
354
|
+
# Subclass provided filter to perform last-minute operations (cleanup, count, etc.) immediately prior to write,
|
355
|
+
# along with option to terminate the actual write if +false+ is returned (for example, to avoid writing
|
356
|
+
# the collection's root node if the collection is empty).
|
357
|
+
def before_write_xml
|
358
|
+
#TODO# This will go away once containers are fully implemented.
|
359
|
+
child_nodes = obtain_class_variable(:@@ooxml_child_nodes)
|
360
|
+
child_nodes.each_pair { |_child_node_name, child_node_params|
|
361
|
+
self.count = self.send(child_node_params[:accessor]).size if child_node_params[:is_array] == :with_count
|
362
|
+
}
|
363
|
+
true
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
# Parent class for defining OOXML based objects (not unlike Rails' +ActiveRecord+!)
|
368
|
+
# Most importantly, provides functionality of parsing such objects from XML,
|
369
|
+
# and marshalling them to XML.
|
370
|
+
class OOXMLObject
|
371
|
+
include OOXMLObjectInstanceMethods
|
372
|
+
end
|
373
|
+
|
374
|
+
# Parent class for OOXML container objects (for example,
|
375
|
+
# <tt><fonts><font>...</font><font>...</font></fonts></tt>
|
376
|
+
# that obscures the top-level container, allowing direct access to the contents as +Array+.
|
377
|
+
class OOXMLContainerObject < Array
|
378
|
+
include OOXMLObjectInstanceMethods
|
379
|
+
|
380
|
+
def initialize(params = {})
|
381
|
+
array_content = params.delete(:_)
|
382
|
+
super
|
383
|
+
array_content.each_with_index { |v, i| self[i] = v } if array_content
|
384
|
+
end
|
385
|
+
|
386
|
+
def get_node_object(child_node_params)
|
387
|
+
if child_node_params[:is_array] then self
|
388
|
+
else super
|
389
|
+
end
|
390
|
+
end
|
391
|
+
protected :get_node_object
|
392
|
+
|
393
|
+
def init_child_nodes(params)
|
394
|
+
obtain_class_variable(:@@ooxml_child_nodes).each_value { |v|
|
395
|
+
next if v[:is_array] # Only one collection node allowed per OOXMLContainerObject, and it is contained in itself.
|
396
|
+
instance_variable_set("@#{v[:accessor]}", params[v[:accessor]])
|
397
|
+
}
|
398
|
+
end
|
399
|
+
protected :init_child_nodes
|
400
|
+
|
401
|
+
def before_write_xml
|
402
|
+
true
|
403
|
+
end
|
404
|
+
|
405
|
+
def inspect
|
406
|
+
vars = [ super ]
|
407
|
+
vars = self.instance_variables.each { |v| vars << "#{v}=#{instance_variable_get(v).inspect}" }
|
408
|
+
"<#{self.class}: #{super} #{vars.join(", ")}>"
|
409
|
+
end
|
410
|
+
|
411
|
+
class << self
|
412
|
+
def define_count_attribute
|
413
|
+
# Count will be inherited from Array. so no need to define it explicitly.
|
414
|
+
define_attribute(:count, :uint, :required => true, :computed => true)
|
415
|
+
end
|
416
|
+
protected :define_count_attribute
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
# Extension class providing functionality for top-level OOXML objects that are represented by
|
421
|
+
# their own <tt>.xml</tt> files in <tt>.xslx</tt> zip container.
|
422
|
+
class OOXMLTopLevelObject < OOXMLObject
|
423
|
+
SAVE_ORDER = 500
|
424
|
+
ROOT = ::Pathname.new('/')
|
425
|
+
|
426
|
+
attr_accessor :root
|
427
|
+
|
428
|
+
# Prototype method. For top-level OOXML object, returns the path at which the current object's XML file
|
429
|
+
# is located within the <tt>.xlsx</tt> zip container.
|
430
|
+
def xlsx_path
|
431
|
+
raise 'Subclass responsebility'
|
432
|
+
end
|
433
|
+
|
434
|
+
# Sets the list of namespaces on this object to be added when writing out XML. Valid only on top-level objects.
|
435
|
+
# === Parameters
|
436
|
+
# * +namespace_hash+ - Hash of namespaces in the form of <tt>"url" => "prefix"</tt>
|
437
|
+
# ==== Examples
|
438
|
+
# set_namespaces('http://schemas.openxmlformats.org/spreadsheetml/2006/main' => nil,
|
439
|
+
# 'http://schemas.openxmlformats.org/officeDocument/2006/relationships' => 'r')
|
440
|
+
def self.set_namespaces(namespace_hash)
|
441
|
+
self.class_variable_set(:@@ooxml_namespaces, namespace_hash)
|
442
|
+
end
|
443
|
+
|
444
|
+
# Generates the top-level OOXML object by parsing its XML file from the contents of the <tt>.xslx</tt> container.
|
445
|
+
# === Parameters
|
446
|
+
# * +zip_file+ - <tt>.xslx</tt> file as <tt>Zip::File</tt> object
|
447
|
+
# * +file_path+ - path to the subject file inside the <tt>.xslx</tt> zip archive
|
448
|
+
def self.parse_file(zip_file, file_path)
|
449
|
+
entry = zip_file.find_entry(RubyXL::from_root(file_path))
|
450
|
+
# Accomodate for Nokogiri Java implementation which is incapable of reading from a stream
|
451
|
+
entry && (entry.get_input_stream { |f| parse(defined?(JRUBY_VERSION) ? f.read : f) })
|
452
|
+
end
|
453
|
+
|
454
|
+
# Saves the contents of the object as XML to respective location in <tt>.xslx</tt> zip container.
|
455
|
+
# === Parameters
|
456
|
+
# * +zipfile+ - ::Zip::File to which the resulting XNMML should be added.
|
457
|
+
def add_to_zip(zip_stream)
|
458
|
+
xml_string = write_xml
|
459
|
+
return false if xml_string.empty?
|
460
|
+
zip_stream.put_next_entry(RubyXL::from_root(self.xlsx_path))
|
461
|
+
zip_stream.write(xml_string)
|
462
|
+
true
|
463
|
+
end
|
464
|
+
|
465
|
+
def file_index
|
466
|
+
root.rels_hash[self.class].index{ |f| f.equal?(self) }.to_i + 1
|
467
|
+
end
|
468
|
+
end
|
469
|
+
end
|