summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--lib/axlsx/drawing/drawing.rb6
-rw-r--r--lib/axlsx/util/constants.rb6
-rw-r--r--lib/axlsx/util/validators.rb2
-rw-r--r--lib/axlsx/workbook/workbook.rb17
-rw-r--r--lib/axlsx/workbook/worksheet/comments.rb115
-rw-r--r--lib/axlsx/workbook/worksheet/worksheet.rb23
-rw-r--r--test/rels/tc_relationship.rb1
-rw-r--r--test/workbook/worksheet/tc_worksheet.rb6
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