mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
fixed some more tests
This commit is contained in:
parent
99d609ce3a
commit
14cb4e88a4
|
@ -3,6 +3,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cxxtest/TestSuite.h>
|
#include <cxxtest/TestSuite.h>
|
||||||
|
|
||||||
|
#include "TemporaryFile.h"
|
||||||
#include "../xlnt.h"
|
#include "../xlnt.h"
|
||||||
|
|
||||||
class DumpTestSuite : public CxxTest::TestSuite
|
class DumpTestSuite : public CxxTest::TestSuite
|
||||||
|
@ -10,37 +11,41 @@ class DumpTestSuite : public CxxTest::TestSuite
|
||||||
public:
|
public:
|
||||||
DumpTestSuite()
|
DumpTestSuite()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _get_test_filename()
|
//_COL_CONVERSION_CACHE = dict((get_column_letter(i), i) for i in range(1, 18279));
|
||||||
{
|
|
||||||
NamedTemporaryFile test_file("w", "xlnt.", ".xlsx", false);
|
|
||||||
test_file.close();
|
|
||||||
return test_file.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
_COL_CONVERSION_CACHE = dict((get_column_letter(i), i) for i in range(1, 18279));
|
|
||||||
|
|
||||||
void test_dump_sheet_title()
|
void test_dump_sheet_title()
|
||||||
{
|
{
|
||||||
test_filename = _get_test_filename();
|
xlnt::workbook wb;
|
||||||
wb = Workbook(optimized_write = True);
|
wb.optimized_write(true);
|
||||||
ws = wb.create_sheet(title = "Test1");
|
auto ws = wb.create_sheet("Test1");
|
||||||
wb.save(test_filename);
|
wb.save(temp_file.GetFilename());
|
||||||
wb2 = load_workbook(test_filename, True);
|
xlnt::workbook wb2;
|
||||||
|
wb2.load(temp_file.GetFilename());
|
||||||
ws = wb2.get_sheet_by_name("Test1");
|
ws = wb2.get_sheet_by_name("Test1");
|
||||||
TS_ASSERT_EQUALS("Test1", ws.title);
|
TS_ASSERT_EQUALS("Test1", ws.get_title());
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_dump_sheet()
|
void test_dump_sheet()
|
||||||
{
|
{
|
||||||
test_filename = _get_test_filename();
|
auto test_filename = temp_file.GetFilename();
|
||||||
wb = Workbook(optimized_write = True);
|
|
||||||
ws = wb.create_sheet();
|
xlnt::workbook wb;
|
||||||
letters = [get_column_letter(x + 1) for x in range(20)];
|
wb.optimized_write(true);
|
||||||
expected_rows = [];
|
auto ws = wb.create_sheet();
|
||||||
for(auto row : range(20))
|
|
||||||
|
std::vector<std::string> letters;
|
||||||
|
|
||||||
|
for(int i = 0; i < 20; i++)
|
||||||
|
{
|
||||||
|
letters.push_back(xlnt::cell::get_column_letter(i + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<xlnt::cell> expected_rows;
|
||||||
|
|
||||||
|
for(int row = 0; row < 20; row++)
|
||||||
{
|
{
|
||||||
expected_rows.append(["%s%d" % (letter, row + 1) for letter in letters]);
|
expected_rows.append(["%s%d" % (letter, row + 1) for letter in letters]);
|
||||||
for(auto row in range(20))
|
for(auto row in range(20))
|
||||||
|
@ -80,41 +85,43 @@ public:
|
||||||
|
|
||||||
void test_table_builder()
|
void test_table_builder()
|
||||||
{
|
{
|
||||||
sb = StringTableBuilder();
|
StringTableBuilder sb;
|
||||||
|
|
||||||
result = {"a":0, "b" : 1, "c" : 2, "d" : 3};
|
std::unordered_map<std::string, int> result = {{"a", 0}, {"b", 1}, {"c", 2}, {"d", 3}};
|
||||||
|
|
||||||
for(auto letter in sorted(result.keys()))
|
for(auto pair : result)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
for x in range(5)
|
sb.add(pair.first);
|
||||||
|
|
||||||
|
auto table = sb.get_table();
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
sb.add(letter)
|
result_items = result.items();
|
||||||
|
}
|
||||||
|
|
||||||
table = dict(sb.get_table())
|
for key, idx in result_items
|
||||||
|
{
|
||||||
try
|
TS_ASSERT_EQUALS(idx, table[key])
|
||||||
{
|
|
||||||
result_items = result.items()
|
|
||||||
}
|
|
||||||
|
|
||||||
for key, idx in result_items
|
|
||||||
{
|
|
||||||
TS_ASSERT_EQUALS(idx, table[key])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_open_too_many_files()
|
void test_open_too_many_files()
|
||||||
{
|
{
|
||||||
test_filename = _get_test_filename();
|
auto test_filename = temp_file.GetFilename();
|
||||||
wb = Workbook(optimized_write = True);
|
|
||||||
|
|
||||||
for i in range(200) over 200 worksheets should raise an OSError("too many open files")
|
xlnt::workbook wb;
|
||||||
|
wb.optimized_write(true);
|
||||||
|
|
||||||
|
for(int i = 0; i < 200; i++) // over 200 worksheets should raise an OSError("too many open files")
|
||||||
{
|
{
|
||||||
wb.create_sheet();
|
wb.create_sheet();
|
||||||
wb.save(test_filename);
|
wb.save(test_filename);
|
||||||
os.remove(test_filename);
|
unlink(test_filename.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,29 +137,37 @@ public:
|
||||||
|
|
||||||
void test_dump_twice()
|
void test_dump_twice()
|
||||||
{
|
{
|
||||||
test_filename = _get_test_filename();
|
auto test_filename = temp_file.GetFilename();
|
||||||
|
|
||||||
wb = Workbook(optimized_write = True);
|
xlnt::workbook wb;
|
||||||
ws = wb.create_sheet();
|
wb.optimized_write(true);
|
||||||
ws.append(["hello"]);
|
auto ws = wb.create_sheet();
|
||||||
|
|
||||||
|
std::vector<std::string> to_append = {"hello"};
|
||||||
|
ws.append(to_append);
|
||||||
|
|
||||||
wb.save(test_filename);
|
wb.save(test_filename);
|
||||||
os.remove(test_filename);
|
unlink(test_filename.c_str());
|
||||||
|
|
||||||
wb.save(test_filename);
|
wb.save(test_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_append_after_save()
|
void test_append_after_save()
|
||||||
{
|
{
|
||||||
test_filename = _get_test_filename();
|
xlnt::workbook wb;
|
||||||
|
wb.optimized_write(true);
|
||||||
|
auto ws = wb.create_sheet();
|
||||||
|
|
||||||
wb = Workbook(optimized_write = True);
|
std::vector<std::string> to_append = {"hello"};
|
||||||
ws = wb.create_sheet();
|
ws.append(to_append);
|
||||||
ws.append(["hello"]);
|
|
||||||
|
|
||||||
wb.save(test_filename);
|
{
|
||||||
os.remove(test_filename);
|
TemporaryFile temp2;
|
||||||
|
wb.save(temp2.GetFilename());
|
||||||
|
}
|
||||||
|
|
||||||
ws.append(["hello"]);
|
ws.append(to_append);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
TemporaryFile temp_file;
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,17 +13,13 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_1()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_get_dimensions()
|
void test_get_dimensions()
|
||||||
{
|
{
|
||||||
expected = ["A1:G5", "D1:K30", "D2:D2", "A1:C1"];
|
auto expected = {"A1:G5", "D1:K30", "D2:D2", "A1:C1"};
|
||||||
|
|
||||||
wb = _open_wb();
|
wb = _open_wb();
|
||||||
for i, sheetn in enumerate(wb.get_sheet_names())
|
|
||||||
|
for(i, sheetn : enumerate(wb.get_sheet_names()))
|
||||||
{
|
{
|
||||||
ws = wb.get_sheet_by_name(name = sheetn);
|
ws = wb.get_sheet_by_name(name = sheetn);
|
||||||
TS_ASSERT_EQUALS(ws._dimensions, expected[i]);
|
TS_ASSERT_EQUALS(ws._dimensions, expected[i]);
|
||||||
|
@ -32,68 +28,68 @@ public:
|
||||||
|
|
||||||
void test_read_fast_integrated()
|
void test_read_fast_integrated()
|
||||||
{
|
{
|
||||||
sheet_name = "Sheet1 - Text"
|
std::string sheet_name = "Sheet1 - Text";
|
||||||
|
|
||||||
expected = [["This is cell A1 in Sheet 1", None, None, None, None, None, None],
|
std::vector<std::vector<char *>> expected = {{"This is cell A1 in Sheet 1", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||||
[None, None, None, None, None, None, None],
|
{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||||
[None, None, None, None, None, None, None],
|
{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||||
[None, None, None, None, None, None, None],
|
{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
|
||||||
[None, None, None, None, None, None, "This is cell G5"], ]
|
{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, "This is cell G5"}};
|
||||||
|
|
||||||
wb = load_workbook(filename = workbook_name, use_iterators = True)
|
wb = load_workbook(filename = workbook_name, use_iterators = True);
|
||||||
ws = wb.get_sheet_by_name(name = sheet_name)
|
ws = wb.get_sheet_by_name(name = sheet_name);
|
||||||
|
|
||||||
for row, expected_row in zip(ws.iter_rows(), expected) :
|
for(row, expected_row : zip(ws.iter_rows(), expected)
|
||||||
|
{
|
||||||
row_values = [x.internal_value for x in row]
|
row_values = [x.internal_value for x in row];
|
||||||
|
TS_ASSERT_EQUALS(row_values, expected_row);
|
||||||
TS_ASSERT_EQUALS(row_values, expected_row)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_get_boundaries_range()
|
void test_get_boundaries_range()
|
||||||
{
|
{
|
||||||
TS_ASSERT_EQUALS(get_range_boundaries("C1:C4"), (3, 1, 3, 4))
|
TS_ASSERT_EQUALS(get_range_boundaries("C1:C4"), (3, 1, 3, 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_get_boundaries_one()
|
void test_get_boundaries_one()
|
||||||
{
|
{
|
||||||
TS_ASSERT_EQUALS(get_range_boundaries("C1"), (3, 1, 4, 1))
|
TS_ASSERT_EQUALS(get_range_boundaries("C1"), (3, 1, 4, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_read_single_cell_range()
|
void test_read_single_cell_range()
|
||||||
{
|
{
|
||||||
wb = load_workbook(filename = workbook_name, use_iterators = True)
|
wb = load_workbook(filename = workbook_name, use_iterators = True);
|
||||||
ws = wb.get_sheet_by_name(name = sheet_name)
|
ws = wb.get_sheet_by_name(name = sheet_name);
|
||||||
|
|
||||||
TS_ASSERT_EQUALS("This is cell A1 in Sheet 1", list(ws.iter_rows("A1"))[0][0].internal_value)
|
TS_ASSERT_EQUALS("This is cell A1 in Sheet 1", list(ws.iter_rows("A1"))[0][0].internal_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_read_fast_integrated2()
|
void test_read_fast_integrated2()
|
||||||
{
|
{
|
||||||
sheet_name = "Sheet2 - Numbers"
|
sheet_name = "Sheet2 - Numbers";
|
||||||
|
|
||||||
expected = [[x + 1] for x in range(30)]
|
expected = [[x + 1] for x in range(30)];
|
||||||
|
|
||||||
query_range = "D1:E30"
|
query_range = "D1:E30";
|
||||||
|
|
||||||
wb = load_workbook(filename = workbook_name, use_iterators = True)
|
wb = load_workbook(filename = workbook_name, use_iterators = True);
|
||||||
ws = wb.get_sheet_by_name(name = sheet_name)
|
ws = wb.get_sheet_by_name(name = sheet_name);
|
||||||
|
|
||||||
for row, expected_row in zip(ws.iter_rows(query_range), expected) :
|
for(row, expected_row : zip(ws.iter_rows(query_range), expected))
|
||||||
|
{
|
||||||
row_values = [x.internal_value for x in row]
|
row_values = [x.internal_value for x in row];
|
||||||
|
TS_ASSERT_EQUALS(row_values, expected_row);
|
||||||
TS_ASSERT_EQUALS(row_values, expected_row)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_read_single_cell_date()
|
void test_read_single_cell_date()
|
||||||
{
|
{
|
||||||
sheet_name = "Sheet4 - Dates"
|
sheet_name = "Sheet4 - Dates";
|
||||||
|
|
||||||
wb = load_workbook(filename = workbook_name, use_iterators = True)
|
wb = load_workbook(filename = workbook_name, use_iterators = True);
|
||||||
ws = wb.get_sheet_by_name(name = sheet_name)
|
ws = wb.get_sheet_by_name(name = sheet_name);
|
||||||
|
|
||||||
TS_ASSERT_EQUALS(datetime.datetime(1973, 5, 20), list(ws.iter_rows("A1"))[0][0].internal_value)
|
TS_ASSERT_EQUALS(datetime.datetime(1973, 5, 20), list(ws.iter_rows("A1"))[0][0].internal_value);
|
||||||
TS_ASSERT_EQUALS(datetime.datetime(1973, 5, 20, 9, 15, 2), list(ws.iter_rows("C1"))[0][0].internal_value)
|
TS_ASSERT_EQUALS(datetime.datetime(1973, 5, 20, 9, 15, 2), list(ws.iter_rows("C1"))[0][0].internal_value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,20 +15,20 @@ public:
|
||||||
|
|
||||||
void test_write_content_types()
|
void test_write_content_types()
|
||||||
{
|
{
|
||||||
wb = Workbook();
|
xlnt::workbook wb;
|
||||||
wb.create_sheet();
|
wb.create_sheet();
|
||||||
wb.create_sheet();
|
wb.create_sheet();
|
||||||
content = write_content_types(wb);
|
auto content = xlnt::workbook::write_content_types(wb);
|
||||||
reference_file = os.path.join(DATADIR, "writer", "expected",
|
std::string reference_file = DATADIR + "/writer/expected/[Content_Types].xml";
|
||||||
"[Content_Types].xml");
|
|
||||||
assert_equals_file_content(reference_file, content);
|
assert_equals_file_content(reference_file, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_write_root_rels()
|
void test_write_root_rels()
|
||||||
{
|
{
|
||||||
wb = Workbook();
|
xlnt::workbook wb;
|
||||||
content = write_root_rels(wb);
|
wb.create_sheet();
|
||||||
reference_file = os.path.join(DATADIR, "writer", "expected", ".rels");
|
auto content = xlnt::workbook::write_root_rels(wb);
|
||||||
|
std::string reference_file = DATADIR + "/writer/expected/.rels";
|
||||||
assert_equals_file_content(reference_file, content);
|
assert_equals_file_content(reference_file, content);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
31
source/tests/TemporaryDirectory.h
Normal file
31
source/tests/TemporaryDirectory.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class TemporaryDirectory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static std::string CreateTemporaryFilename()
|
||||||
|
{
|
||||||
|
std::array<char, L_tmpnam> buffer;
|
||||||
|
tmpnam(buffer.data());
|
||||||
|
return std::string(buffer.begin(), buffer.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
TemporaryDirectory() : filename_(CreateTemporaryFilename())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
~TemporaryDirectory()
|
||||||
|
{
|
||||||
|
remove(filename_.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetFilename() const { return filename_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string filename_;
|
||||||
|
};
|
31
source/tests/TemporaryFile.h
Normal file
31
source/tests/TemporaryFile.h
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class TemporaryFile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static std::string CreateTemporaryFilename()
|
||||||
|
{
|
||||||
|
std::array<char, L_tmpnam> buffer;
|
||||||
|
tmpnam(buffer.data());
|
||||||
|
return std::string(buffer.begin(), buffer.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
TemporaryFile() : filename_(CreateTemporaryFilename())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
~TemporaryFile()
|
||||||
|
{
|
||||||
|
remove(filename_.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetFilename() const { return filename_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string filename_;
|
||||||
|
};
|
|
@ -34,7 +34,9 @@ public:
|
||||||
|
|
||||||
void test_set_bad_title()
|
void test_set_bad_title()
|
||||||
{
|
{
|
||||||
Worksheet(wb, "X" * 50);
|
std::string title(50, 'X');
|
||||||
|
xlnt::workbook wb;
|
||||||
|
wb.create_sheet(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_set_bad_title_character()
|
void test_set_bad_title_character()
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <cxxtest/TestSuite.h>
|
#include <cxxtest/TestSuite.h>
|
||||||
|
|
||||||
#include "../xlnt.h"
|
#include "../xlnt.h"
|
||||||
|
#include "TemporaryDirectory.h"
|
||||||
|
|
||||||
class WriteTestSuite : public CxxTest::TestSuite
|
class WriteTestSuite : public CxxTest::TestSuite
|
||||||
{
|
{
|
||||||
|
@ -15,12 +16,11 @@ public:
|
||||||
|
|
||||||
void test_write_empty_workbook()
|
void test_write_empty_workbook()
|
||||||
{
|
{
|
||||||
make_tmpdir();
|
TemporaryDirectory temp_dir;
|
||||||
wb = Workbook();
|
wb = Workbook();
|
||||||
dest_filename = os.path.join(TMPDIR, "empty_book.xlsx");
|
dest_filename = os.path.join(TMPDIR, "empty_book.xlsx");
|
||||||
save_workbook(wb, dest_filename);
|
save_workbook(wb, dest_filename);
|
||||||
assert os.path.isfile(dest_filename);
|
assert os.path.isfile(dest_filename);
|
||||||
clean_tmpdir();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_write_virtual_workbook()
|
void test_write_virtual_workbook()
|
||||||
|
|
167
source/xlnt.cpp
167
source/xlnt.cpp
|
@ -6,6 +6,7 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include "xlnt.h"
|
#include "xlnt.h"
|
||||||
|
#include "../third-party/pugixml/src/pugixml.hpp"
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
@ -971,6 +972,8 @@ struct cell_struct
|
||||||
bool bool_value;
|
bool bool_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::string error_value;
|
||||||
tm date_value;
|
tm date_value;
|
||||||
std::string string_value;
|
std::string string_value;
|
||||||
std::string formula_value;
|
std::string formula_value;
|
||||||
|
@ -1015,12 +1018,27 @@ cell::cell(cell_struct *root) : root_(root)
|
||||||
|
|
||||||
cell::type cell::data_type_for_value(const std::string &value)
|
cell::type cell::data_type_for_value(const std::string &value)
|
||||||
{
|
{
|
||||||
|
if(value[0] == '=')
|
||||||
|
{
|
||||||
|
return type::formula;
|
||||||
|
}
|
||||||
|
|
||||||
return type::null;
|
return type::null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cell::set_explicit_value(const std::string &value, type data_type)
|
void cell::set_explicit_value(const std::string &value, type data_type)
|
||||||
{
|
{
|
||||||
|
root_->type = data_type;
|
||||||
|
switch(data_type)
|
||||||
|
{
|
||||||
|
case type::formula: root_->formula_value = value; return;
|
||||||
|
case type::date: root_->date_value.tm_hour = std::stoi(value); return;
|
||||||
|
case type::error: root_->error_value = value; return;
|
||||||
|
case type::boolean: root_->bool_value = value == "true"; return;
|
||||||
|
case type::null: return;
|
||||||
|
case type::numeric: root_->numeric_value = std::stod(value); return;
|
||||||
|
case type::string: root_->string_value = value; return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cell::bind_value()
|
bool cell::bind_value()
|
||||||
|
@ -1620,17 +1638,17 @@ void worksheet::unmerge_cells(int start_row, int start_column, int end_row, int
|
||||||
root_->unmerge_cells(start_row, start_column, end_row, end_column);
|
root_->unmerge_cells(start_row, start_column, end_row, end_column);
|
||||||
}
|
}
|
||||||
|
|
||||||
void worksheet::append(const std::vector<xlnt::cell> &cells)
|
void worksheet::append(const std::vector<std::string> &cells)
|
||||||
{
|
{
|
||||||
root_->append(cells);
|
root_->append(cells);
|
||||||
}
|
}
|
||||||
|
|
||||||
void worksheet::append(const std::unordered_map<std::string, xlnt::cell> &cells)
|
void worksheet::append(const std::unordered_map<std::string, std::string> &cells)
|
||||||
{
|
{
|
||||||
root_->append(cells);
|
root_->append(cells);
|
||||||
}
|
}
|
||||||
|
|
||||||
void worksheet::append(const std::unordered_map<int, xlnt::cell> &cells)
|
void worksheet::append(const std::unordered_map<int, std::string> &cells)
|
||||||
{
|
{
|
||||||
root_->append(cells);
|
root_->append(cells);
|
||||||
}
|
}
|
||||||
|
@ -1676,11 +1694,146 @@ cell worksheet::operator[](const std::string &address)
|
||||||
return cell(address);
|
return cell(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
workbook::workbook() : active_worksheet_(nullptr)
|
std::string workbook::write_content_types(workbook &wb)
|
||||||
|
{
|
||||||
|
std::set<std::string> seen;
|
||||||
|
|
||||||
|
pugi::xml_node root;
|
||||||
|
|
||||||
|
if(wb.has_vba_archive())
|
||||||
|
{
|
||||||
|
root = fromstring(wb.get_vba_archive().read(ARC_CONTENT_TYPES));
|
||||||
|
|
||||||
|
for(auto elem : root.findall("{" + CONTYPES_NS + "}Override"))
|
||||||
|
{
|
||||||
|
seen.insert(elem.attrib["PartName"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
root = Element("{" + CONTYPES_NS + "}Types");
|
||||||
|
|
||||||
|
for(auto content_type : static_content_types_config)
|
||||||
|
{
|
||||||
|
if(setting_type == "Override")
|
||||||
|
{
|
||||||
|
tag = "{" + CONTYPES_NS + "}Override";
|
||||||
|
attrib = {"PartName": "/" + name};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tag = "{" + CONTYPES_NS + "}Default";
|
||||||
|
attrib = {"Extension": name};
|
||||||
|
}
|
||||||
|
|
||||||
|
attrib["ContentType"] = content_type;
|
||||||
|
SubElement(root, tag, attrib);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int drawing_id = 1;
|
||||||
|
int chart_id = 1;
|
||||||
|
int comments_id = 1;
|
||||||
|
int sheet_id = 0;
|
||||||
|
|
||||||
|
for(auto sheet : wb)
|
||||||
|
{
|
||||||
|
std::string name = "/xl/worksheets/sheet" + std::to_string(sheet_id) + ".xml";
|
||||||
|
|
||||||
|
if(seen.find(name) == seen.end())
|
||||||
|
{
|
||||||
|
SubElement(root, "{" + CONTYPES_NS + "}Override", {{"PartName", name},
|
||||||
|
{"ContentType", "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"}});
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sheet._charts || sheet._images)
|
||||||
|
{
|
||||||
|
name = "/xl/drawings/drawing" + drawing_id + ".xml";
|
||||||
|
|
||||||
|
if(seen.find(name) == seen.end())
|
||||||
|
{
|
||||||
|
SubElement(root, "{%s}Override" % CONTYPES_NS, {"PartName" : name,
|
||||||
|
"ContentType" : "application/vnd.openxmlformats-officedocument.drawing+xml"});
|
||||||
|
}
|
||||||
|
|
||||||
|
drawing_id += 1;
|
||||||
|
|
||||||
|
for(auto chart : sheet._charts)
|
||||||
|
{
|
||||||
|
name = "/xl/charts/chart%d.xml" % chart_id;
|
||||||
|
|
||||||
|
if(seen.find(name) == seen.end())
|
||||||
|
{
|
||||||
|
SubElement(root, "{%s}Override" % CONTYPES_NS, {"PartName" : name,
|
||||||
|
"ContentType" : "application/vnd.openxmlformats-officedocument.drawingml.chart+xml"});
|
||||||
|
}
|
||||||
|
|
||||||
|
chart_id += 1;
|
||||||
|
|
||||||
|
if(chart._shapes)
|
||||||
|
{
|
||||||
|
name = "/xl/drawings/drawing%d.xml" % drawing_id;
|
||||||
|
|
||||||
|
if(seen.find(name) == seen.end())
|
||||||
|
{
|
||||||
|
SubElement(root, "{%s}Override" % CONTYPES_NS, {"PartName" : name,
|
||||||
|
"ContentType" : "application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml"});
|
||||||
|
}
|
||||||
|
|
||||||
|
drawing_id += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(sheet.get_comment_count() > 0)
|
||||||
|
{
|
||||||
|
SubElement(root, "{%s}Override" % CONTYPES_NS,
|
||||||
|
{"PartName": "/xl/comments%d.xml" % comments_id,
|
||||||
|
"ContentType" : "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml"});
|
||||||
|
comments_id += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return get_document_content(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string workbook::write_root_rels(workbook wb)
|
||||||
|
{
|
||||||
|
root = Element("{%s}Relationships" % PKG_REL_NS);
|
||||||
|
relation_tag = "{%s}Relationship" % PKG_REL_NS;
|
||||||
|
SubElement(root, relation_tag, {"Id": "rId1", "Target" : ARC_WORKBOOK,
|
||||||
|
"Type" : "%s/officeDocument" % REL_NS});
|
||||||
|
SubElement(root, relation_tag, {"Id": "rId2", "Target" : ARC_CORE,
|
||||||
|
"Type" : "%s/metadata/core-properties" % PKG_REL_NS});
|
||||||
|
SubElement(root, relation_tag, {"Id": "rId3", "Target" : ARC_APP,
|
||||||
|
"Type" : "%s/extended-properties" % REL_NS});
|
||||||
|
if(wb.has_vba_archive())
|
||||||
|
{
|
||||||
|
// See if there was a customUI relation and reuse its id
|
||||||
|
arc = fromstring(workbook.vba_archive.read(ARC_ROOT_RELS));
|
||||||
|
rels = arc.findall(relation_tag);
|
||||||
|
rId = None;
|
||||||
|
for(rel in rels)
|
||||||
|
{
|
||||||
|
if(rel.get("Target") == ARC_CUSTOM_UI)
|
||||||
|
{
|
||||||
|
rId = rel.get("Id");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(rId is not None)
|
||||||
|
{
|
||||||
|
SubElement(root, relation_tag, {"Id": rId, "Target" : ARC_CUSTOM_UI,
|
||||||
|
"Type" : "%s" % CUSTOMUI_NS});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return get_document_content(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
workbook::workbook() : active_sheet_index_(0)
|
||||||
{
|
{
|
||||||
auto ws = create_sheet();
|
auto ws = create_sheet();
|
||||||
ws.set_title("Sheet1");
|
ws.set_title("Sheet1");
|
||||||
active_worksheet_ = ws;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
worksheet workbook::get_sheet_by_name(const std::string &name)
|
worksheet workbook::get_sheet_by_name(const std::string &name)
|
||||||
|
@ -1695,7 +1848,7 @@ worksheet workbook::get_sheet_by_name(const std::string &name)
|
||||||
|
|
||||||
worksheet workbook::get_active_sheet()
|
worksheet workbook::get_active_sheet()
|
||||||
{
|
{
|
||||||
return active_worksheet_;
|
return worksheets_[active_sheet_index_];
|
||||||
}
|
}
|
||||||
|
|
||||||
worksheet workbook::create_sheet()
|
worksheet workbook::create_sheet()
|
||||||
|
|
464
source/xlnt.h
464
source/xlnt.h
|
@ -12,17 +12,21 @@ struct tm;
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
struct cell_struct;
|
|
||||||
struct worksheet_struct;
|
|
||||||
struct package_impl;
|
|
||||||
|
|
||||||
class style;
|
|
||||||
class worksheet;
|
|
||||||
class worksheet;
|
|
||||||
class cell;
|
class cell;
|
||||||
class relationship;
|
class comment;
|
||||||
class workbook;
|
class drawing;
|
||||||
|
class named_range;
|
||||||
class package;
|
class package;
|
||||||
|
class relationship;
|
||||||
|
class style;
|
||||||
|
class workbook;
|
||||||
|
class worksheet;
|
||||||
|
|
||||||
|
struct cell_struct;
|
||||||
|
struct drawing_struct;
|
||||||
|
struct named_range_struct;
|
||||||
|
struct package_impl;
|
||||||
|
struct worksheet_struct;
|
||||||
|
|
||||||
const int MIN_ROW = 0;
|
const int MIN_ROW = 0;
|
||||||
const int MIN_COLUMN = 0;
|
const int MIN_COLUMN = 0;
|
||||||
|
@ -192,6 +196,12 @@ enum class target_mode
|
||||||
Internal
|
Internal
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class encoding_type
|
||||||
|
{
|
||||||
|
utf8,
|
||||||
|
latin1
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a value type that may or may not have an assigned value.
|
/// Represents a value type that may or may not have an assigned value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -798,25 +808,278 @@ struct coordinate
|
||||||
int row;
|
int row;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Alignment options for use in styles.
|
||||||
|
/// </summary>
|
||||||
|
struct alignment
|
||||||
|
{
|
||||||
|
enum class horizontal_alignment
|
||||||
|
{
|
||||||
|
general,
|
||||||
|
left,
|
||||||
|
right,
|
||||||
|
center,
|
||||||
|
center_continuous,
|
||||||
|
justify
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class vertical_alignment
|
||||||
|
{
|
||||||
|
bottom,
|
||||||
|
top,
|
||||||
|
center,
|
||||||
|
justify
|
||||||
|
};
|
||||||
|
|
||||||
|
horizontal_alignment horizontal = horizontal_alignment::general;
|
||||||
|
vertical_alignment vertical = vertical_alignment::bottom;
|
||||||
|
int text_rotation = 0;
|
||||||
|
bool wrap_text = false;
|
||||||
|
bool shrink_to_fit = false;
|
||||||
|
int indent = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class number_format
|
class number_format
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void set_format_code(const std::string &format_code) { format_code_ = format_code; }
|
enum class format
|
||||||
|
{
|
||||||
|
general,
|
||||||
|
text,
|
||||||
|
number,
|
||||||
|
number00,
|
||||||
|
number_comma_separated1,
|
||||||
|
number_comma_separated2,
|
||||||
|
percentage,
|
||||||
|
percentage00,
|
||||||
|
date_yyyymmdd2,
|
||||||
|
date_yyyymmdd,
|
||||||
|
date_ddmmyyyy,
|
||||||
|
date_dmyslash,
|
||||||
|
date_dmyminus,
|
||||||
|
date_dmminus,
|
||||||
|
date_myminus,
|
||||||
|
date_xlsx14,
|
||||||
|
date_xlsx15,
|
||||||
|
date_xlsx16,
|
||||||
|
date_xlsx17,
|
||||||
|
date_xlsx22,
|
||||||
|
date_datetime,
|
||||||
|
date_time1,
|
||||||
|
date_time2,
|
||||||
|
date_time3,
|
||||||
|
date_time4,
|
||||||
|
date_time5,
|
||||||
|
date_time6,
|
||||||
|
date_time7,
|
||||||
|
date_time8,
|
||||||
|
date_timedelta,
|
||||||
|
date_yyyymmddslash,
|
||||||
|
currency_usd_simple,
|
||||||
|
currency_usd,
|
||||||
|
currency_eur_simple
|
||||||
|
};
|
||||||
|
|
||||||
|
static const std::unordered_map<int, std::string> builtin_formats;
|
||||||
|
|
||||||
|
static std::string builtin_format_code(int index);
|
||||||
|
|
||||||
|
static bool is_date_format(const std::string &format);
|
||||||
|
static bool is_builtin(const std::string &format);
|
||||||
|
|
||||||
|
format get_format_code() const { return format_code_; }
|
||||||
|
void set_format_code(format format_code) { format_code_ = format_code; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string format_code_;
|
format format_code_ = format::general;
|
||||||
|
int format_index_ = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct color
|
||||||
|
{
|
||||||
|
static const color black;
|
||||||
|
static const color white;
|
||||||
|
static const color red;
|
||||||
|
static const color darkred;
|
||||||
|
static const color blue;
|
||||||
|
static const color darkblue;
|
||||||
|
static const color green;
|
||||||
|
static const color darkgreen;
|
||||||
|
static const color yellow;
|
||||||
|
static const color darkyellow;
|
||||||
|
|
||||||
|
color(int index)
|
||||||
|
{
|
||||||
|
this->index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index;
|
||||||
|
};
|
||||||
|
|
||||||
|
class font
|
||||||
|
{
|
||||||
|
enum class underline
|
||||||
|
{
|
||||||
|
none,
|
||||||
|
double_,
|
||||||
|
double_accounting,
|
||||||
|
single,
|
||||||
|
single_accounting
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string name = "Calibri";
|
||||||
|
int size = 11;
|
||||||
|
bool bold = false;
|
||||||
|
bool italic = false;
|
||||||
|
bool superscript = false;
|
||||||
|
bool subscript = false;
|
||||||
|
underline underline = underline::none;
|
||||||
|
bool strikethrough = false;
|
||||||
|
color color = color::black;
|
||||||
|
};
|
||||||
|
|
||||||
|
class fill
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class type
|
||||||
|
{
|
||||||
|
none,
|
||||||
|
solid,
|
||||||
|
gradient_linear,
|
||||||
|
gradient_path,
|
||||||
|
pattern_darkdown,
|
||||||
|
pattern_darkgray,
|
||||||
|
pattern_darkgrid,
|
||||||
|
pattern_darkhorizontal,
|
||||||
|
pattern_darktrellis,
|
||||||
|
pattern_darkup,
|
||||||
|
pattern_darkvertical,
|
||||||
|
pattern_gray0625,
|
||||||
|
pattern_gray125,
|
||||||
|
pattern_lightdown,
|
||||||
|
pattern_lightgray,
|
||||||
|
pattern_lightgrid,
|
||||||
|
pattern_lighthorizontal,
|
||||||
|
pattern_lighttrellis,
|
||||||
|
pattern_lightup,
|
||||||
|
pattern_lightvertical,
|
||||||
|
pattern_mediumgray,
|
||||||
|
};
|
||||||
|
|
||||||
|
type type = type::none;
|
||||||
|
int rotation = 0;
|
||||||
|
color start_color = color::white;
|
||||||
|
color end_color = color::black;
|
||||||
|
};
|
||||||
|
|
||||||
|
class borders
|
||||||
|
{
|
||||||
|
struct border
|
||||||
|
{
|
||||||
|
enum class style
|
||||||
|
{
|
||||||
|
none,
|
||||||
|
dashdot,
|
||||||
|
dashdotdot,
|
||||||
|
dashed,
|
||||||
|
dotted,
|
||||||
|
double_,
|
||||||
|
hair,
|
||||||
|
medium,
|
||||||
|
mediumdashdot,
|
||||||
|
mediumdashdotdot,
|
||||||
|
mediumdashed,
|
||||||
|
slantdashdot,
|
||||||
|
thick,
|
||||||
|
thin
|
||||||
|
};
|
||||||
|
|
||||||
|
style style = style::none;
|
||||||
|
color color = color::black;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class diagonal_direction
|
||||||
|
{
|
||||||
|
none,
|
||||||
|
up,
|
||||||
|
down,
|
||||||
|
both
|
||||||
|
};
|
||||||
|
|
||||||
|
border left;
|
||||||
|
border right;
|
||||||
|
border top;
|
||||||
|
border bottom;
|
||||||
|
border diagonal;
|
||||||
|
diagonal_direction diagonal_direction = diagonal_direction::none;
|
||||||
|
border all_borders;
|
||||||
|
border outline;
|
||||||
|
border inside;
|
||||||
|
border vertical;
|
||||||
|
border horizontal;
|
||||||
|
};
|
||||||
|
|
||||||
|
class protection
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class type
|
||||||
|
{
|
||||||
|
inherit,
|
||||||
|
protected_,
|
||||||
|
unprotected
|
||||||
|
};
|
||||||
|
|
||||||
|
type locked;
|
||||||
|
type hidden;
|
||||||
};
|
};
|
||||||
|
|
||||||
class style
|
class style
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
style(bool static_ = false) : static_(static_) {}
|
||||||
|
|
||||||
|
style copy() const;
|
||||||
|
|
||||||
|
font get_font() const;
|
||||||
|
void set_font(font font);
|
||||||
|
|
||||||
|
fill get_fill() const;
|
||||||
|
void set_fill(fill fill);
|
||||||
|
|
||||||
|
borders get_borders() const;
|
||||||
|
void set_borders(borders borders);
|
||||||
|
|
||||||
|
alignment get_alignment() const;
|
||||||
|
void set_alignment(alignment alignment);
|
||||||
|
|
||||||
number_format &get_number_format() { return number_format_; }
|
number_format &get_number_format() { return number_format_; }
|
||||||
const number_format &get_number_format() const { return number_format_; }
|
const number_format &get_number_format() const { return number_format_; }
|
||||||
|
void set_number_format(number_format number_format);
|
||||||
|
|
||||||
|
protection get_protection() const;
|
||||||
|
void set_protection(protection protection);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
style(const style &rhs);
|
||||||
|
|
||||||
|
bool static_ = false;
|
||||||
|
font font_;
|
||||||
|
fill fill_;
|
||||||
|
borders borders_;
|
||||||
|
alignment alignment_;
|
||||||
number_format number_format_;
|
number_format number_format_;
|
||||||
|
protection protection_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Describes cell associated properties.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Properties of interest include style, type, value, and address.
|
||||||
|
/// The Cell class is required to know its value and type, display options,
|
||||||
|
/// and any other features of an Excel cell.Utilities for referencing
|
||||||
|
/// cells using Excel's 'A1' column/row nomenclature are also provided.
|
||||||
|
/// </remarks>
|
||||||
class cell
|
class cell
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -833,15 +1096,46 @@ public:
|
||||||
|
|
||||||
static const std::unordered_map<std::string, int> ErrorCodes;
|
static const std::unordered_map<std::string, int> ErrorCodes;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert a coordinate string like 'B12' to a tuple ('B', 12)
|
||||||
|
/// </summary>
|
||||||
static coordinate coordinate_from_string(const std::string &address);
|
static coordinate coordinate_from_string(const std::string &address);
|
||||||
static int column_index_from_string(const std::string &column_string);
|
|
||||||
static std::string get_column_letter(int column_index);
|
/// <summary>
|
||||||
|
/// Convert a coordinate to an absolute coordinate string (B12 -> $B$12)
|
||||||
|
/// </summary>
|
||||||
static std::string absolute_coordinate(const std::string &absolute_address);
|
static std::string absolute_coordinate(const std::string &absolute_address);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert a column letter into a column number (e.g. B -> 2)
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Excel only supports 1 - 3 letter column names from A->ZZZ, so we
|
||||||
|
/// restrict our column names to 1 - 3 characters, each in the range A - Z.
|
||||||
|
/// </remarks>
|
||||||
|
static int column_index_from_string(const std::string &column_string);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert a column number into a column letter (3 -> 'C')
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Right shift the column col_idx by 26 to find column letters in reverse
|
||||||
|
/// order.These numbers are 1 - based, and can be converted to ASCII
|
||||||
|
/// ordinals by adding 64.
|
||||||
|
/// </remarks>
|
||||||
|
static std::string get_column_letter(int column_index);
|
||||||
|
|
||||||
|
static std::string check_string(const std::string &value);
|
||||||
|
static std::string check_numeric(const std::string &value);
|
||||||
|
static std::string check_error(const std::string &value);
|
||||||
|
|
||||||
cell();
|
cell();
|
||||||
cell(worksheet &ws, const std::string &column, int row);
|
cell(worksheet &ws, const std::string &column, int row);
|
||||||
cell(worksheet &ws, const std::string &column, int row, const std::string &initial_value);
|
cell(worksheet &ws, const std::string &column, int row, const std::string &initial_value);
|
||||||
|
|
||||||
|
encoding_type get_encoding() const;
|
||||||
|
std::string to_string() const;
|
||||||
|
|
||||||
void set_explicit_value(const std::string &value, type data_type);
|
void set_explicit_value(const std::string &value, type data_type);
|
||||||
type data_type_for_value(const std::string &value);
|
type data_type_for_value(const std::string &value);
|
||||||
|
|
||||||
|
@ -853,32 +1147,59 @@ public:
|
||||||
bool bind_value(bool value);
|
bool bind_value(bool value);
|
||||||
bool bind_value(const tm &value);
|
bool bind_value(const tm &value);
|
||||||
|
|
||||||
|
std::string get_hyperlink() const;
|
||||||
|
void set_hyperlink(const std::string &value);
|
||||||
|
|
||||||
|
std::string get_hyperlink_rel_id() const;
|
||||||
|
|
||||||
|
void set_number_format(const std::string &format_code);
|
||||||
|
|
||||||
|
bool has_style() const;
|
||||||
|
|
||||||
|
style &get_style();
|
||||||
|
const style &get_style() const;
|
||||||
|
|
||||||
|
type get_data_type() const;
|
||||||
|
|
||||||
|
std::string get_coordinate() const;
|
||||||
|
std::string get_address() const;
|
||||||
|
|
||||||
|
cell get_offset(int row, int column);
|
||||||
|
|
||||||
|
bool is_date() const;
|
||||||
|
|
||||||
|
std::pair<int, int> get_anchor() const;
|
||||||
|
|
||||||
|
comment get_comment() const;
|
||||||
|
void set_comment(comment comment);
|
||||||
|
|
||||||
|
cell &operator=(const cell &rhs);
|
||||||
|
cell &operator=(bool value);
|
||||||
cell &operator=(int value);
|
cell &operator=(int value);
|
||||||
cell &operator=(double value);
|
cell &operator=(double value);
|
||||||
cell &operator=(const std::string &value);
|
cell &operator=(const std::string &value);
|
||||||
cell &operator=(const char *value);
|
cell &operator=(const char *value);
|
||||||
cell &operator=(bool value);
|
|
||||||
cell &operator=(const tm &value);
|
cell &operator=(const tm &value);
|
||||||
|
|
||||||
|
bool operator==(std::nullptr_t) const;
|
||||||
|
bool operator==(bool comparand) const;
|
||||||
|
bool operator==(int comparand) const;
|
||||||
|
bool operator==(double comparand) const;
|
||||||
bool operator==(const std::string &comparand) const;
|
bool operator==(const std::string &comparand) const;
|
||||||
bool operator==(const char *comparand) const;
|
bool operator==(const char *comparand) const;
|
||||||
bool operator==(const tm &comparand) const;
|
bool operator==(const tm &comparand) const;
|
||||||
|
|
||||||
|
friend bool operator==(std::nullptr_t, const cell &cell);
|
||||||
|
friend bool operator==(bool comparand, const cell &cell);
|
||||||
|
friend bool operator==(int comparand, const cell &cell);
|
||||||
|
friend bool operator==(double comparand, const cell &cell);
|
||||||
friend bool operator==(const std::string &comparand, const cell &cell);
|
friend bool operator==(const std::string &comparand, const cell &cell);
|
||||||
friend bool operator==(const char *comparand, const cell &cell);
|
friend bool operator==(const char *comparand, const cell &cell);
|
||||||
friend bool operator==(const tm &comparand, const cell &cell);
|
friend bool operator==(const tm &comparand, const cell &cell);
|
||||||
|
|
||||||
std::string to_string() const;
|
|
||||||
bool is_date() const;
|
|
||||||
style &get_style();
|
|
||||||
const style &get_style() const;
|
|
||||||
type get_data_type() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend struct worksheet_struct;
|
friend struct worksheet_struct;
|
||||||
|
|
||||||
cell(cell_struct *root);
|
cell(cell_struct *root);
|
||||||
|
|
||||||
cell_struct *root_;
|
cell_struct *root_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -951,9 +1272,9 @@ public:
|
||||||
void merge_cells(int start_row, int start_column, int end_row, int end_column);
|
void merge_cells(int start_row, int start_column, int end_row, int end_column);
|
||||||
void unmerge_cells(const std::string &range_string);
|
void unmerge_cells(const std::string &range_string);
|
||||||
void unmerge_cells(int start_row, int start_column, int end_row, int end_column);
|
void unmerge_cells(int start_row, int start_column, int end_row, int end_column);
|
||||||
void append(const std::vector<xlnt::cell> &cells);
|
void append(const std::vector<std::string> &cells);
|
||||||
void append(const std::unordered_map<std::string, xlnt::cell> &cells);
|
void append(const std::unordered_map<std::string, std::string> &cells);
|
||||||
void append(const std::unordered_map<int, xlnt::cell> &cells);
|
void append(const std::unordered_map<int, std::string> &cells);
|
||||||
xlnt::range rows() const;
|
xlnt::range rows() const;
|
||||||
xlnt::range columns() const;
|
xlnt::range columns() const;
|
||||||
bool operator==(const worksheet &other) const;
|
bool operator==(const worksheet &other) const;
|
||||||
|
@ -967,26 +1288,111 @@ private:
|
||||||
worksheet_struct *root_;
|
worksheet_struct *root_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class named_range
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
named_range(const std::string &name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class worksheet;
|
||||||
|
named_range(named_range_struct *root);
|
||||||
|
named_range_struct *root_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class drawing
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
drawing();
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class worksheet;
|
||||||
|
drawing(drawing_struct *root);
|
||||||
|
drawing_struct *root_;
|
||||||
|
};
|
||||||
|
|
||||||
class workbook
|
class workbook
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static std::string write_content_types(workbook &wb);
|
||||||
|
static std::string write_root_rels(workbook &wb);
|
||||||
|
|
||||||
|
//constructors
|
||||||
workbook();
|
workbook();
|
||||||
|
|
||||||
|
//prevent copy and assignment
|
||||||
workbook(const workbook &) = delete;
|
workbook(const workbook &) = delete;
|
||||||
const workbook &operator=(const workbook &) = delete;
|
const workbook &operator=(const workbook &) = delete;
|
||||||
|
|
||||||
worksheet get_sheet_by_name(const std::string &sheet_name);
|
//named parameters
|
||||||
|
workbook &optimized_write(bool value);
|
||||||
|
workbook &encoding(encoding_type value);
|
||||||
|
workbook &guess_types(bool value);
|
||||||
|
workbook &data_only(bool value);
|
||||||
|
|
||||||
|
void read_workbook_settings(const std::string &xml_source);
|
||||||
|
|
||||||
|
//getters
|
||||||
worksheet get_active_sheet();
|
worksheet get_active_sheet();
|
||||||
|
bool get_optimized_write() const { return optimized_write_; }
|
||||||
|
encoding_type get_encoding() const { return encoding_; }
|
||||||
|
bool get_guess_types() const { return guess_types_; }
|
||||||
|
bool get_data_only() const { return data_only_; }
|
||||||
|
|
||||||
|
//create
|
||||||
worksheet create_sheet();
|
worksheet create_sheet();
|
||||||
worksheet create_sheet(std::size_t index);
|
worksheet create_sheet(std::size_t index);
|
||||||
std::vector<std::string> get_sheet_names() const;
|
worksheet create_sheet(const std::string &title);
|
||||||
|
worksheet create_sheet(std::size_t index, const std::string &title);
|
||||||
|
|
||||||
|
//add
|
||||||
|
void add_sheet(worksheet worksheet);
|
||||||
|
void add_sheet(worksheet worksheet, std::size_t index);
|
||||||
|
|
||||||
|
//remove
|
||||||
|
void remove_sheet(worksheet worksheet);
|
||||||
|
|
||||||
|
//container operations
|
||||||
|
worksheet get_sheet_by_name(const std::string &sheet_name);
|
||||||
|
|
||||||
|
bool contains(const std::string &key) const;
|
||||||
|
|
||||||
|
int get_index(worksheet worksheet);
|
||||||
|
|
||||||
|
worksheet operator[](const std::string &name);
|
||||||
|
|
||||||
std::vector<worksheet>::iterator begin();
|
std::vector<worksheet>::iterator begin();
|
||||||
std::vector<worksheet>::iterator end();
|
std::vector<worksheet>::iterator end();
|
||||||
worksheet operator[](const std::string &name);
|
|
||||||
|
std::vector<worksheet>::const_iterator begin() const;
|
||||||
|
std::vector<worksheet>::const_iterator end() const;
|
||||||
|
|
||||||
|
std::vector<worksheet>::const_iterator cbegin() const;
|
||||||
|
std::vector<worksheet>::const_iterator cend() const;
|
||||||
|
|
||||||
|
std::vector<std::string> get_sheet_names() const;
|
||||||
|
|
||||||
|
//named ranges
|
||||||
|
void create_named_range(const std::string &name, worksheet worksheet, const std::string &range_string);
|
||||||
|
std::vector<named_range> get_named_ranges();
|
||||||
|
void add_named_range(named_range named_range);
|
||||||
|
void get_named_range(const std::string &name);
|
||||||
|
void remove_named_range(named_range named_range);
|
||||||
|
|
||||||
|
//serialization
|
||||||
void save(const std::string &filename);
|
void save(const std::string &filename);
|
||||||
|
void load(const std::string &filename);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
worksheet active_worksheet_;
|
bool optimized_write_;
|
||||||
|
bool optimized_read_;
|
||||||
|
bool guess_types_;
|
||||||
|
bool data_only_;
|
||||||
|
int active_sheet_index_;
|
||||||
|
encoding_type encoding_;
|
||||||
std::vector<worksheet> worksheets_;
|
std::vector<worksheet> worksheets_;
|
||||||
|
std::vector<named_range> named_ranges_;
|
||||||
|
std::vector<relationship> relationships_;
|
||||||
|
std::vector<drawing> drawings_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace xlnt
|
} // namespace xlnt
|
||||||
|
|
Loading…
Reference in New Issue
Block a user