mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
intermediate commit
This commit is contained in:
parent
9d312ee7f4
commit
342184139f
|
@ -26,6 +26,7 @@
|
|||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <xlnt/xlnt_config.hpp>
|
||||
|
@ -33,7 +34,10 @@
|
|||
namespace xlnt {
|
||||
|
||||
class cell;
|
||||
template<typename T>
|
||||
class optional;
|
||||
class path;
|
||||
class workbook;
|
||||
class worksheet;
|
||||
|
||||
namespace detail {
|
||||
|
@ -55,24 +59,23 @@ public:
|
|||
void close();
|
||||
|
||||
/// <summary>
|
||||
/// Registers callback as the function to be called when a cell is read.
|
||||
/// Reads the next cell in the current worksheet and optionally returns it if
|
||||
/// the last cell in the sheet has not yet been read.
|
||||
/// </summary>
|
||||
void on_cell(std::function<void(cell)> callback);
|
||||
cell read_cell();
|
||||
|
||||
/// <summary>
|
||||
/// Registers callback as the function to be called when a worksheet is
|
||||
/// opened for reading. The callback will be called with the title of the
|
||||
/// worksheet.
|
||||
/// Beings reading of the next worksheet in the workbook and optionally
|
||||
/// returns its title if the last worksheet has not yet been read.
|
||||
/// </summary>
|
||||
void on_worksheet_start(std::function<void(std::string)> callback);
|
||||
std::string begin_worksheet();
|
||||
|
||||
/// <summary>
|
||||
/// Registers callback as the function to be called when a worksheet is
|
||||
/// finished being read. The callback will be called with the worksheet
|
||||
/// object (which will not contain any cells). Cells should be handled
|
||||
/// via registering a callback with on_cell.
|
||||
/// Ends reading of the current worksheet in the workbook and optionally
|
||||
/// returns a worksheet object corresponding to the worksheet with the title
|
||||
/// returned by begin_worksheet().
|
||||
/// </summary>
|
||||
void on_worksheet_end(std::function<void(worksheet)> callback);
|
||||
worksheet end_worksheet();
|
||||
|
||||
/// <summary>
|
||||
/// Interprets byte vector data as an XLSX file and sets the content of this
|
||||
|
@ -107,7 +110,8 @@ public:
|
|||
void open(std::istream &stream);
|
||||
|
||||
private:
|
||||
std::unique_ptr<xlnt::detail::xlsx_consumer> consumer_;
|
||||
std::unique_ptr<detail::xlsx_consumer> consumer_;
|
||||
std::unique_ptr<workbook> workbook_;
|
||||
};
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <xlnt/cell/cell.hpp>
|
||||
#include <xlnt/cell/comment.hpp>
|
||||
#include <xlnt/packaging/manifest.hpp>
|
||||
#include <xlnt/utils/optional.hpp>
|
||||
#include <xlnt/utils/path.hpp>
|
||||
#include <xlnt/workbook/workbook.hpp>
|
||||
#include <xlnt/worksheet/worksheet.hpp>
|
||||
|
@ -135,7 +136,28 @@ xlsx_consumer::xlsx_consumer(workbook &target)
|
|||
void xlsx_consumer::read(std::istream &source)
|
||||
{
|
||||
archive_.reset(new izstream(source));
|
||||
populate_workbook();
|
||||
populate_workbook(false);
|
||||
}
|
||||
|
||||
void xlsx_consumer::open(std::istream &source)
|
||||
{
|
||||
archive_.reset(new izstream(source));
|
||||
populate_workbook(true);
|
||||
}
|
||||
|
||||
cell xlsx_consumer::read_cell()
|
||||
{
|
||||
return cell(nullptr);
|
||||
}
|
||||
|
||||
std::string xlsx_consumer::begin_worksheet()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
worksheet xlsx_consumer::end_worksheet()
|
||||
{
|
||||
return worksheet(nullptr);
|
||||
}
|
||||
|
||||
xml::parser &xlsx_consumer::parser()
|
||||
|
@ -179,7 +201,7 @@ std::vector<relationship> xlsx_consumer::read_relationships(const path &part)
|
|||
return relationships;
|
||||
}
|
||||
|
||||
void xlsx_consumer::read_part(const std::vector<relationship> &rel_chain)
|
||||
void xlsx_consumer::read_part(const std::vector<relationship> &rel_chain, bool streaming)
|
||||
{
|
||||
const auto &manifest = target_.manifest();
|
||||
const auto part_path = manifest.canonicalize(rel_chain);
|
||||
|
@ -203,7 +225,7 @@ void xlsx_consumer::read_part(const std::vector<relationship> &rel_chain)
|
|||
break;
|
||||
|
||||
case relationship_type::office_document:
|
||||
read_office_document(manifest.content_type(part_path));
|
||||
read_office_document(manifest.content_type(part_path), streaming);
|
||||
break;
|
||||
|
||||
case relationship_type::connections:
|
||||
|
@ -315,7 +337,7 @@ void xlsx_consumer::read_part(const std::vector<relationship> &rel_chain)
|
|||
parser_ = nullptr;
|
||||
}
|
||||
|
||||
void xlsx_consumer::populate_workbook()
|
||||
void xlsx_consumer::populate_workbook(bool streaming)
|
||||
{
|
||||
target_.clear();
|
||||
|
||||
|
@ -335,7 +357,7 @@ void xlsx_consumer::populate_workbook()
|
|||
continue;
|
||||
}
|
||||
|
||||
read_part({package_rel});
|
||||
read_part({package_rel}, streaming);
|
||||
}
|
||||
|
||||
for (const auto &relationship_source_string : archive_->files())
|
||||
|
@ -347,7 +369,7 @@ void xlsx_consumer::populate_workbook()
|
|||
}
|
||||
|
||||
read_part({ manifest().relationship(root_path,
|
||||
relationship_type::office_document) });
|
||||
relationship_type::office_document) }, true);
|
||||
}
|
||||
|
||||
// Package Parts
|
||||
|
@ -442,7 +464,7 @@ void xlsx_consumer::read_custom_properties()
|
|||
expect_end_element(qn("custom-properties", "Properties"));
|
||||
}
|
||||
|
||||
void xlsx_consumer::read_office_document(const std::string &content_type) // CT_Workbook
|
||||
void xlsx_consumer::read_office_document(const std::string &content_type, bool streaming) // CT_Workbook
|
||||
{
|
||||
if (content_type != "application/vnd."
|
||||
"openxmlformats-officedocument.spreadsheetml.sheet.main+xml"
|
||||
|
@ -634,22 +656,33 @@ void xlsx_consumer::read_office_document(const std::string &content_type) // CT_
|
|||
|
||||
if (manifest().has_relationship(workbook_path, relationship_type::shared_string_table))
|
||||
{
|
||||
read_part({workbook_rel, manifest().relationship(workbook_path, relationship_type::shared_string_table)});
|
||||
read_part({workbook_rel,
|
||||
manifest().relationship(workbook_path,
|
||||
relationship_type::shared_string_table)}, false);
|
||||
}
|
||||
|
||||
if (manifest().has_relationship(workbook_path, relationship_type::stylesheet))
|
||||
{
|
||||
read_part({workbook_rel, manifest().relationship(workbook_path, relationship_type::stylesheet)});
|
||||
read_part({workbook_rel,
|
||||
manifest().relationship(workbook_path,
|
||||
relationship_type::stylesheet)}, false);
|
||||
}
|
||||
|
||||
if (manifest().has_relationship(workbook_path, relationship_type::theme))
|
||||
{
|
||||
read_part({workbook_rel, manifest().relationship(workbook_path, relationship_type::theme)});
|
||||
read_part({workbook_rel,
|
||||
manifest().relationship(workbook_path,
|
||||
relationship_type::theme)}, false);
|
||||
}
|
||||
|
||||
if (streaming)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto worksheet_rel : manifest().relationships(workbook_path, relationship_type::worksheet))
|
||||
{
|
||||
read_part({workbook_rel, worksheet_rel});
|
||||
read_part({workbook_rel, worksheet_rel}, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1358,15 +1391,19 @@ void xlsx_consumer::read_stylesheet()
|
|||
|
||||
void xlsx_consumer::read_theme()
|
||||
{
|
||||
auto workbook_rel = manifest().relationship(path("/"), relationship_type::office_document);
|
||||
auto theme_rel = manifest().relationship(workbook_rel.target().path(), relationship_type::theme);
|
||||
auto workbook_rel = manifest().relationship(path("/"),
|
||||
relationship_type::office_document);
|
||||
auto theme_rel = manifest().relationship(workbook_rel.target().path(),
|
||||
relationship_type::theme);
|
||||
auto theme_path = manifest().canonicalize({workbook_rel, theme_rel});
|
||||
|
||||
target_.theme(theme());
|
||||
|
||||
if (manifest().has_relationship(theme_path, relationship_type::image))
|
||||
{
|
||||
read_part({workbook_rel, theme_rel, manifest().relationship(theme_path, relationship_type::image)});
|
||||
read_part({workbook_rel, theme_rel,
|
||||
manifest().relationship(theme_path,
|
||||
relationship_type::image)}, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
|
@ -36,9 +37,12 @@
|
|||
|
||||
namespace xlnt {
|
||||
|
||||
class cell;
|
||||
class color;
|
||||
class rich_text;
|
||||
class manifest;
|
||||
template<typename T>
|
||||
class optional;
|
||||
class path;
|
||||
class relationship;
|
||||
class variant;
|
||||
|
@ -57,6 +61,30 @@ class xlsx_consumer
|
|||
public:
|
||||
xlsx_consumer(workbook &destination);
|
||||
|
||||
void open(std::istream &source);
|
||||
|
||||
/// <summary>
|
||||
/// Reads the next cell in the current worksheet and optionally returns it if
|
||||
/// the last cell in the sheet has not yet been read. An exception will be thrown
|
||||
/// if this is not open as a streaming consumer.
|
||||
/// </summary>
|
||||
cell read_cell();
|
||||
|
||||
/// <summary>
|
||||
/// Beings reading of the next worksheet in the workbook and optionally
|
||||
/// returns its title if the last worksheet has not yet been read. An
|
||||
/// exception will be thrown if this is not open as a streaming consumer.
|
||||
/// </summary>
|
||||
std::string begin_worksheet();
|
||||
|
||||
/// <summary>
|
||||
/// Ends reading of the current worksheet in the workbook and optionally
|
||||
/// returns a worksheet object corresponding to the worksheet with the title
|
||||
/// returned by begin_worksheet(). An exception will be thrown if this is
|
||||
/// not open as a streaming consumer.
|
||||
/// </summary>
|
||||
worksheet end_worksheet();
|
||||
|
||||
void read(std::istream &source);
|
||||
|
||||
void read(std::istream &source, const std::string &password);
|
||||
|
@ -66,7 +94,7 @@ private:
|
|||
/// Read all the files needed from the XLSX archive and initialize all of
|
||||
/// the data in the workbook to match.
|
||||
/// </summary>
|
||||
void populate_workbook();
|
||||
void populate_workbook(bool streaming);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
|
@ -96,7 +124,7 @@ private:
|
|||
/// Parse the main XML document about the workbook and then all child relationships
|
||||
/// of the workbook (e.g. worksheets).
|
||||
/// </summary>
|
||||
void read_office_document(const std::string &content_type);
|
||||
void read_office_document(const std::string &content_type, bool streaming);
|
||||
|
||||
// Workbook Relationship Target Parts
|
||||
|
||||
|
@ -257,7 +285,7 @@ private:
|
|||
/// xlsx_consumer::parser() will return a reference to the parser that reads
|
||||
/// this part.
|
||||
/// </summary>
|
||||
void read_part(const std::vector<relationship> &rel_chain);
|
||||
void read_part(const std::vector<relationship> &rel_chain, bool streaming);
|
||||
|
||||
/// <summary>
|
||||
/// libstudxml will throw an exception if all attributes on an element are not
|
||||
|
|
|
@ -22,8 +22,15 @@
|
|||
// @license: http://www.opensource.org/licenses/mit-license.php
|
||||
// @author: see AUTHORS file
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include <detail/serialization/vector_streambuf.hpp>
|
||||
#include <detail/serialization/xlsx_consumer.hpp>
|
||||
#include <xlnt/cell/cell.hpp>
|
||||
#include <xlnt/utils/optional.hpp>
|
||||
#include <xlnt/workbook/streaming_workbook_reader.hpp>
|
||||
#include <xlnt/workbook/workbook.hpp>
|
||||
#include <xlnt/worksheet/worksheet.hpp>
|
||||
|
||||
namespace xlnt {
|
||||
|
||||
|
@ -40,46 +47,52 @@ void streaming_workbook_reader::close()
|
|||
}
|
||||
}
|
||||
|
||||
void streaming_workbook_reader::on_cell(std::function<void(cell)> callback)
|
||||
cell streaming_workbook_reader::read_cell()
|
||||
{
|
||||
//consumer_->on_cell(callback);
|
||||
return consumer_->read_cell();
|
||||
}
|
||||
|
||||
void streaming_workbook_reader::on_worksheet_start(std::function<void(std::string)> callback)
|
||||
std::string streaming_workbook_reader::begin_worksheet()
|
||||
{
|
||||
//consumer_->on_worksheet_start(callback);
|
||||
return consumer_->begin_worksheet();
|
||||
}
|
||||
|
||||
void streaming_workbook_reader::on_worksheet_end(std::function<void(worksheet)> callback)
|
||||
worksheet streaming_workbook_reader::end_worksheet()
|
||||
{
|
||||
//consumer_->on_worksheet_end(callback);
|
||||
return consumer_->end_worksheet();
|
||||
}
|
||||
|
||||
void streaming_workbook_reader::open(const std::vector<std::uint8_t> &data)
|
||||
{
|
||||
|
||||
detail::vector_istreambuf buffer(data);
|
||||
std::istream buffer_stream(&buffer);
|
||||
open(buffer_stream);
|
||||
}
|
||||
|
||||
void streaming_workbook_reader::open(const std::string &filename)
|
||||
{
|
||||
|
||||
std::ifstream file_stream(filename, std::ios::binary);
|
||||
open(file_stream);
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
void streaming_workbook_reader::open(const std::wstring &filename)
|
||||
{
|
||||
|
||||
std::ifstream file_stream(filename, std::ios::binary);
|
||||
open(file_stream);
|
||||
}
|
||||
#endif
|
||||
|
||||
void streaming_workbook_reader::open(const xlnt::path &filename)
|
||||
{
|
||||
|
||||
open(filename.string());
|
||||
}
|
||||
|
||||
void streaming_workbook_reader::open(std::istream &stream)
|
||||
{
|
||||
|
||||
workbook_.reset(new workbook());
|
||||
consumer_.reset(new detail::xlsx_consumer(*workbook_));
|
||||
consumer_->open(stream);
|
||||
}
|
||||
|
||||
} // namespace xlnt
|
||||
|
|
Loading…
Reference in New Issue
Block a user