diff options
| -rw-r--r-- | lib/axlsx/drawing/drawing.rb | 6 | ||||
| -rw-r--r-- | lib/axlsx/util/constants.rb | 6 | ||||
| -rw-r--r-- | lib/axlsx/util/validators.rb | 2 | ||||
| -rw-r--r-- | lib/axlsx/workbook/workbook.rb | 17 | ||||
| -rw-r--r-- | lib/axlsx/workbook/worksheet/comments.rb | 115 | ||||
| -rw-r--r-- | lib/axlsx/workbook/worksheet/worksheet.rb | 23 | ||||
| -rw-r--r-- | test/rels/tc_relationship.rb | 1 | ||||
| -rw-r--r-- | test/workbook/worksheet/tc_worksheet.rb | 6 |
8 files changed, 166 insertions, 10 deletions
diff --git a/lib/axlsx/drawing/drawing.rb b/lib/axlsx/drawing/drawing.rb index 17b6e0b5..dfdd0075 100644 --- a/lib/axlsx/drawing/drawing.rb +++ b/lib/axlsx/drawing/drawing.rb @@ -146,8 +146,10 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - str << '<?xml version="1.0" encoding="UTF-8"?>' - str << '<xdr:wsDr xmlns:xdr="' << XML_NS_XDR << '" xmlns:a="' << XML_NS_A << '" xmlns:c="' << XML_NS_C << '">' + str << '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +# str << '<xdr:wsDr xmlns:xdr="' << XML_NS_XDR << '" xmlns:a="' << XML_NS_A << '" xmlns:c="' << XML_NS_C << '">' + str << '<xdr:wsDr xmlns:xdr="' << XML_NS_XDR << '" xmlns:a="' << XML_NS_A << '">' + anchors.each { |anchor| anchor.to_xml_string(str) } str << '</xdr:wsDr>' end diff --git a/lib/axlsx/util/constants.rb b/lib/axlsx/util/constants.rb index 0699a482..985c6e53 100644 --- a/lib/axlsx/util/constants.rb +++ b/lib/axlsx/util/constants.rb @@ -79,6 +79,9 @@ module Axlsx # image rels namespace HYPERLINK_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" + # comment rels namespace + COMMENT_R = "http://purl.oclc.org/ooxml/officeDocument/relationships/comments" + # table content type TABLE_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml" @@ -181,6 +184,9 @@ module Axlsx # chart part IMAGE_PN = "media/image%d.%s" + # comment part + COMMENT_PN = "xl/comments%d.xml" + # location of schema files for validation SCHEMA_BASE = File.dirname(__FILE__)+'/../../schema/' diff --git a/lib/axlsx/util/validators.rb b/lib/axlsx/util/validators.rb index dd86ff56..1ee0d75e 100644 --- a/lib/axlsx/util/validators.rb +++ b/lib/axlsx/util/validators.rb @@ -195,7 +195,7 @@ module Axlsx # XML_NS_R, TABLE_R, WORKBOOK_R, WORKSHEET_R, APP_R, RELS_R, CORE_R, STYLES_R, CHART_R, DRAWING_R, IMAGE_R, HYPERLINK_R, SHARED_STRINGS_R are allowed # @param [Any] v The value validated def self.validate_relationship_type(v) - RestrictionValidator.validate :relationship_type, [XML_NS_R, TABLE_R, WORKBOOK_R, WORKSHEET_R, APP_R, RELS_R, CORE_R, STYLES_R, CHART_R, DRAWING_R, IMAGE_R, HYPERLINK_R, SHARED_STRINGS_R], v + RestrictionValidator.validate :relationship_type, [XML_NS_R, TABLE_R, WORKBOOK_R, WORKSHEET_R, APP_R, RELS_R, CORE_R, STYLES_R, CHART_R, DRAWING_R, IMAGE_R, HYPERLINK_R, SHARED_STRINGS_R, COMMENT_R], v end # Requires that the value is a valid table element type diff --git a/lib/axlsx/workbook/workbook.rb b/lib/axlsx/workbook/workbook.rb index aeedec61..38336af3 100644 --- a/lib/axlsx/workbook/workbook.rb +++ b/lib/axlsx/workbook/workbook.rb @@ -14,6 +14,7 @@ require 'axlsx/workbook/worksheet/conditional_formatting.rb' require 'axlsx/workbook/worksheet/conditional_formatting_rule.rb' require 'axlsx/workbook/worksheet/row.rb' require 'axlsx/workbook/worksheet/col.rb' +require 'axlsx/workbook/worksheet/comments.rb' require 'axlsx/workbook/worksheet/worksheet.rb' require 'axlsx/workbook/shared_strings_table.rb' require 'axlsx/workbook/worksheet/table.rb' @@ -84,6 +85,9 @@ require 'axlsx/workbook/worksheet/table.rb' # @return [SimpleTypedList] attr_reader :drawings + # pretty sure this two are always empty and can be removed. + + # A colllection of tables associated with this workbook # @note The recommended way to manage drawings is Worksheet#add_table # @see Worksheet#add_table @@ -92,6 +96,14 @@ require 'axlsx/workbook/worksheet/table.rb' attr_reader :tables + # A colllection of comments associated with this workbook + # @note The recommended way to manage comments is Worksheet#add_comment + # @see Worksheet#add_comment + # @see Comment + # @return [SimpleTypedList] + attr_reader :comments + + # The styles associated with this workbook # @note The recommended way to manage styles is Styles#add_style # @see Style#add_style @@ -125,7 +137,12 @@ require 'axlsx/workbook/worksheet/table.rb' @drawings = SimpleTypedList.new Drawing @charts = SimpleTypedList.new Chart @images = SimpleTypedList.new Pic + + # Are these even used????? Check package serialization parts @tables = SimpleTypedList.new Table + @comments = SimpleTypedList.new Comments + + @use_autowidth = true self.date1904= !options[:date1904].nil? && options[:date1904] diff --git a/lib/axlsx/workbook/worksheet/comments.rb b/lib/axlsx/workbook/worksheet/comments.rb new file mode 100644 index 00000000..310adb8f --- /dev/null +++ b/lib/axlsx/workbook/worksheet/comments.rb @@ -0,0 +1,115 @@ +module Axlsx + + class Comments + + # a collection of the comment authors + # @return [SimpleTypedList] + attr_reader :authors + + # a collection of comment objects + # @return [SimpleTypedList] + attr_reader :comment_list + + + # The worksheet that these comments belong to + # @return [Worksheet] + attr_reader :worksheet + + # Creates a new Comments object + # @param [Worksheet] worksheet The sheet that these comments belong to. + def initialize(worksheet) + raise ArgumentError, "you must provide a worksheet" unless worksheet.is_a?(Worksheet) + @worksheet = worksheet + @authors = SimpleTypedList.new String + @comment_list = SimpleTypedList.new Comment + end + + # Adds a new comment to the worksheet that owns these comments. + # @note the author, text and ref options are required + # @option options [String] author The name of the author for this comment + # @option options [String] text The text for this comment + # @option options [Stirng|Cell] ref The cell that this comment is attached to. + def add_comment(options={}) + raise ArgumentError, "Comment require an author" unless options[:author] + raise ArgumentError, "Comment requires text" unless options[:text] + raise ArgumentError, "Comment requires ref" unless options[:ref] + options[:author_index] = @authors.index(options[:author]) || @authors << options[:author] + @comment_list << Comment.new(self, options) + @comment_list.last + end + + def to_xml_string(str="") + str << '<?xml version="1.0" encoding="UTF-8"?>' + str << '<comments xmlns="' << XML_NS << '">' + str << '<authors>' + authors.each do |author| + str << '<author>' << author.to_s << '</author>' + end + str << '</authors>' + str << '<commentList>' + comment_list.each do |comment| + comment.to_xml_string str + end + str << '<commentList></comments>' + + end + + end + + class Comment + + attr_reader :text + + attr_reader :author_index + + attr_reader :comments + + attr_reader :ref + # TODO + # r (Rich Text Run) + # rPh (Phonetic Text Run) + # phoneticPr (Phonetic Properties) + def initialize(comments, options={}) + raise ArgumentError, "A comment needs a parent comments object" unless comments.is_a?(Comments) + @comments = comments + options.each do |o| + self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" + end + yield self if block_given? + end + + def pn + "#{COMMENT_PN % (index+1)}" + end + + # The index of this comment + # @return [Integer] + def index + @comments.comment_list.index(self) + end + + def ref=(v) + Axlsx::DataTypeValidator.validate "Comment.ref", [String, Cell], v + @ref = v if v.is_a?(String) + @ref = v.r if v.is_a?(Cell) + end + + def text=(v) + Axlsx::validate_string(v) + @text = v + end + + def author_index=(v) + Axlsx::validate_unsigned_int(v) + @author_index = v + end + + def to_xml_string(str = "") + str << '<comment ref="' << ref << '" authorId="' << author_index << '">' + str << '<t xml:space="preserve">' << text << '</t>' + str << '</comment>' + end + + end + +end diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb index 8f91d629..24120aa1 100644 --- a/lib/axlsx/workbook/worksheet/worksheet.rb +++ b/lib/axlsx/workbook/worksheet/worksheet.rb @@ -148,7 +148,7 @@ module Axlsx @merged_cells = [] @auto_fit_data = [] @conditional_formattings = [] - + @comments = Comments.new(self) @selected = false @show_gridlines = true self.name = "Sheet" + (index+1).to_s @@ -442,6 +442,12 @@ module Axlsx table end + + # Shortcut to comments#add_comment + def add_comment(options={}) + @comments.add_comment(options) + end + # Adds a media item to the worksheets drawing # @param [Class] media_type # @option options [] unknown @@ -487,12 +493,15 @@ module Axlsx # The worksheet relationships. This is managed automatically by the worksheet # @return [Relationships] def relationships - r = Relationships.new - @tables.each do |table| - r << Relationship.new(TABLE_R, "../#{table.pn}") - end - r << Relationship.new(DRAWING_R, "../#{@drawing.pn}") if @drawing - r + r = Relationships.new + @tables.each do |table| + r << Relationship.new(TABLE_R, "../#{table.pn}") + end + @comments.comment_list.each do |comment| + r << Relationship.new(COMMENT_R, "#{comment.pn}") + end + r << Relationship.new(DRAWING_R, "../#{@drawing.pn}") if @drawing + r end # Returns the cell or cells defined using excel style A1:B3 references. diff --git a/test/rels/tc_relationship.rb b/test/rels/tc_relationship.rb index 98f21b0b..ef995449 100644 --- a/test/rels/tc_relationship.rb +++ b/test/rels/tc_relationship.rb @@ -10,6 +10,7 @@ class TestRelationships < Test::Unit::TestCase def test_type assert_raise(ArgumentError) { Axlsx::Relationship.new 'type', 'target' } assert_nothing_raised { Axlsx::Relationship.new Axlsx::WORKSHEET_R, 'target' } + assert_nothing_raised { Axlsx::Relationship.new Axlsx::COMMENT_R, 'target' } end def test_target_mode diff --git a/test/workbook/worksheet/tc_worksheet.rb b/test/workbook/worksheet/tc_worksheet.rb index a16713b5..dbb48887 100644 --- a/test/workbook/worksheet/tc_worksheet.rb +++ b/test/workbook/worksheet/tc_worksheet.rb @@ -70,6 +70,7 @@ class TestWorksheet < Test::Unit::TestCase assert_equal(optioned.name, 'bob') assert_equal(optioned.selected, true) assert_equal(optioned.show_gridlines, false) + end @@ -321,11 +322,16 @@ class TestWorksheet < Test::Unit::TestCase end def test_relationships + @ws.add_row [1,2,3] assert(@ws.relationships.empty?, "No Drawing relationship until you add a chart") c = @ws.add_chart Axlsx::Pie3DChart assert_equal(@ws.relationships.size, 1, "adding a chart creates the relationship") c = @ws.add_chart Axlsx::Pie3DChart assert_equal(@ws.relationships.size, 1, "multiple charts still only result in one relationship") + c = @ws.add_comment :text => 'builder', :author => 'bob', :ref => @ws.rows.last.cells.last + assert_equal(@ws.relationships.size, 2, "adding a comment adds a relationship") + c = @ws.add_comment :text => 'not that is a comment!', :author => 'travis', :ref => "A1" + assert_equal(@ws.relationships.size, 3, "adding multiple comments result in multiple relationships") end |
