lib/axlsx/package.rb in axlsx-1.0.16 vs lib/axlsx/package.rb in axlsx-1.0.17

- old
+ new

@@ -1,12 +1,12 @@ -# -*- coding: utf-8 -*- +# encoding: UTF-8 module Axlsx # Package is responsible for managing all the bits and peices that Open Office XML requires to make a valid # xlsx document including valdation and serialization. class Package - # plain text password + # provides access to the app doc properties for this package # see App attr_reader :app # provides access to the core doc properties for the package @@ -15,18 +15,35 @@ # Initializes your package # # @param [Hash] options A hash that you can use to specify the author and workbook for this package. # @option options [String] :author The author of the document + # @option options [Boolean] :use_shared_strings This is passed to the workbook to specify that shared strings should be used when serializing the package. # @example Package.new :author => 'you!', :workbook => Workbook.new def initialize(options={}) @workbook = nil @core, @app = Core.new, App.new @core.creator = options[:author] || @core.creator + options.each do |o| + self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" + end yield self if block_given? end + # Shortcut to specify that the workbook should use shared strings + # @see Workbook#use_shared_strings + def use_shared_strings=(v) + Axlsx::validate_boolean(v); + workbook.use_shared_strings = v + end + + # Shortcut to determine if the workbook is configured to use shared strings + # @see Workbook#use_shared_strings + def use_shared_strings + workbook.use_shared_strings + end + # The workbook this package will serialize or validate. # @return [Workbook] If no workbook instance has been assigned with this package a new Workbook instance is returned. # @raise ArgumentError if workbook parameter is not a Workbook instance. # @note As there are multiple ways to instantiate a workbook for the package, # here are a few examples: @@ -55,10 +72,11 @@ # Serialize your workbook to disk as an xlsx document. # # @param [File] output The file you want to serialize your package to # @param [Boolean] confirm_valid Validate the package prior to serialization. + # @option options stream indicates if we should be writing to a stream or a file. True for stream, nil for file # @return [Boolean] False if confirm_valid and validation errors exist. True if the package was serialized # @note A tremendous amount of effort has gone into ensuring that you cannot create invalid xlsx documents. # confirm_valid should be used in the rare case that you cannot open the serialized file. # @see Package#validate # @example @@ -68,30 +86,32 @@ # Package.new.serialize(f) # # # You will find a file called test.xlsx def serialize(output, confirm_valid=false) return false unless !confirm_valid || self.validate.empty? - p = parts Zip::ZipOutputStream.open(output) do |zip| - p.each do |part| - unless part[:doc].nil? - zip.put_next_entry(part[:entry]); - entry = ['1.9.2', '1.9.3'].include?(RUBY_VERSION) ? part[:doc].force_encoding('BINARY') : part[:doc] - zip.puts(entry) - end - unless part[:path].nil? - zip.put_next_entry(part[:entry]); - # binread for 1.9.3 - zip.write IO.respond_to?(:binread) ? IO.binread(part[:path]) : IO.read(part[:path]) - end - end + write_parts(zip) end true end + + + # Serialize your workbook to a StringIO instance + # @param [Boolean] confirm_valid Validate the package prior to serialization. + # @return [StringIO|Boolean] False if confirm_valid and validation errors exist. rewound string IO if not. + def to_stream(confirm_valid=false) + return false unless !confirm_valid || self.validate.empty? + zip = write_parts(Zip::ZipOutputStream.new("streamed", true)) + stream = zip.close_buffer + stream.rewind + stream + end # Encrypt the package into a CFB using the password provided + # This is not ready yet def encrypt(file_name, password) + return false moc = MsOffCrypto.new(file_name, password) moc.save end # Validate all parts of the package against xsd schema. @@ -115,10 +135,30 @@ errors end private + # Writes the package parts to a zip archive. + # @param [Zip::ZipOutputStream] zip + # @return [Zip::ZipOutputStream] + def write_parts(zip) + p = parts + p.each do |part| + unless part[:doc].nil? + zip.put_next_entry(part[:entry]); + entry = ['1.9.2', '1.9.3'].include?(RUBY_VERSION) ? part[:doc].force_encoding('BINARY') : part[:doc] + zip.puts(entry) + end + unless part[:path].nil? + zip.put_next_entry(part[:entry]); + # binread for 1.9.3 + zip.write IO.respond_to?(:binread) ? IO.binread(part[:path]) : IO.read(part[:path]) + end + end + zip + end + # The parts of a package # @return [Array] An array of hashes that define the entry, document and schema for each part of the package. # @private def parts @parts = [ @@ -141,10 +181,14 @@ workbook.images.each do |image| @parts << {:entry => "xl/#{image.pn}", :path => image.image_src} end + if use_shared_strings + @parts << {:entry => "xl/#{SHARED_STRINGS_PN}", :doc => workbook.shared_strings.to_xml, :schema => SML_XSD} + end + workbook.worksheets.each do |sheet| @parts << {:entry => "xl/#{sheet.rels_pn}", :doc => sheet.relationships.to_xml, :schema => RELS_XSD} @parts << {:entry => "xl/#{sheet.pn}", :doc => sheet.to_xml, :schema => SML_XSD} end @parts @@ -192,9 +236,13 @@ GIF_CT elsif ext == 'png' PNG_CT end c_types << Axlsx::Default.new(:ContentType => ct, :Extension => ext ) + end + if use_shared_strings + c_types << Axlsx::Override.new(:PartName => "/xl/#{SHARED_STRINGS_PN}", + :ContentType => SHARED_STRINGS_CT) end c_types end # Creates the minimum content types for generating a valid xlsx document.