From dc1a80ebaeecd60e0269bf00bd8e6e1eada76b87 Mon Sep 17 00:00:00 2001 From: Thomas Fussell Date: Sun, 18 May 2014 21:29:19 -0400 Subject: [PATCH] fix some more things --- source/tests/CellTestSuite.h | 2 +- source/tests/IterTestSuite.h | 98 ------- source/tests/PathHelper.h | 44 ++++ source/tests/PropsTestSuite.h | 5 - source/tests/ReadTestSuite.h | 192 +++++++------- source/tests/ThemeTestSuite.h | 12 +- source/tests/UnicodeTestSuite.h | 21 -- source/tests/WorkbookTestSuite.h | 416 +++++++++++------------------- source/tests/WorksheetTestSuite.h | 95 +++++-- source/tests/runner-autogen.cpp | 278 +++++--------------- source/xlnt.cpp | 289 +++++++++++++++++++-- source/xlnt.h | 51 +++- 12 files changed, 755 insertions(+), 748 deletions(-) delete mode 100644 source/tests/IterTestSuite.h create mode 100644 source/tests/PathHelper.h delete mode 100644 source/tests/UnicodeTestSuite.h diff --git a/source/tests/CellTestSuite.h b/source/tests/CellTestSuite.h index ca38c196..adac9814 100644 --- a/source/tests/CellTestSuite.h +++ b/source/tests/CellTestSuite.h @@ -283,7 +283,7 @@ public: void test_repr() { xlnt::workbook wb; - xlnt::worksheet ws = wb.get_active_sheet(); + xlnt::worksheet ws = wb.get_active_sheet(); xlnt::cell cell(ws, "A", 1); TS_ASSERT_EQUALS(cell.to_string(), ""); diff --git a/source/tests/IterTestSuite.h b/source/tests/IterTestSuite.h deleted file mode 100644 index a97e3327..00000000 --- a/source/tests/IterTestSuite.h +++ /dev/null @@ -1,98 +0,0 @@ -#pragma once - -#include -#include - -#include "../xlnt.h" - -class IterTestSuite : public CxxTest::TestSuite -{ -public: - IterTestSuite() - { - - } - - void test_get_dimensions() - { - /* - auto expected = {"A1:G5", "D1:K30", "D2:D2", "A1:C1"}; - - std::string workbook_name = DATADIR + "/genuine/empty.xlsx"; - xlnt::workbook wb; - wb.load(workbook_name); - - for(i, sheetn : enumerate(wb.get_sheet_names())) - { - ws = wb.get_sheet_by_name(name = sheetn); - TS_ASSERT_EQUALS(ws._dimensions, expected[i]); - }*/ - } - - void test_read_fast_integrated() - { - /*std::string sheet_name = "Sheet1 - Text"; - - std::vector> expected = {{"This is cell A1 in Sheet 1", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}, - {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}, - {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}, - {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}, - {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, "This is cell G5"}}; - - wb = load_workbook(filename = workbook_name, use_iterators = True); - ws = wb.get_sheet_by_name(name = sheet_name); - - for(row, expected_row : zip(ws.iter_rows(), expected) - { - row_values = [x.internal_value for x in row]; - TS_ASSERT_EQUALS(row_values, expected_row); - }*/ - } - - void test_get_boundaries_range() - { - //TS_ASSERT_EQUALS(get_range_boundaries("C1:C4"), (3, 1, 3, 4)); - } - - void test_get_boundaries_one() - { - //TS_ASSERT_EQUALS(get_range_boundaries("C1"), (3, 1, 4, 1)); - } - - void test_read_single_cell_range() - { - /*wb = load_workbook(filename = workbook_name, use_iterators = True); - 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);*/ - } - - void test_read_fast_integrated2() - { - /*sheet_name = "Sheet2 - Numbers"; - - expected = [[x + 1] for x in range(30)]; - - query_range = "D1:E30"; - - wb = load_workbook(filename = workbook_name, use_iterators = True); - ws = wb.get_sheet_by_name(name = sheet_name); - - for(row, expected_row : zip(ws.iter_rows(query_range), expected)) - { - row_values = [x.internal_value for x in row]; - TS_ASSERT_EQUALS(row_values, expected_row); - }*/ - } - - void test_read_single_cell_date() - { - //sheet_name = "Sheet4 - Dates"; - - //wb = load_workbook(filename = workbook_name, use_iterators = True); - //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, 9, 15, 2), list(ws.iter_rows("C1"))[0][0].internal_value); - } -}; diff --git a/source/tests/PathHelper.h b/source/tests/PathHelper.h new file mode 100644 index 00000000..bbc3ba5a --- /dev/null +++ b/source/tests/PathHelper.h @@ -0,0 +1,44 @@ +#pragma once + +#ifdef __APPLE__ +#include +#elif defined(_WIN32) +#include +#endif + +class PathHelper +{ +public: + static std::string GetExecutableDirectory() + { +#ifdef __APPLE__ + std::array path; + uint32_t size = static_cast(path.size()); + if (_NSGetExecutablePath(path.data(), &size) == 0) + { + return std::string(path.begin(), std::find(path.begin(), path.end(), '\0') - 9); + } + throw std::runtime_error("buffer too small, " + std::to_string(path.size()) + ", should be: " + std::to_string(size)); +#elif defined(_WIN32) + std::array path; + DWORD result = GetModuleFileName(nullptr, buffer.data(), buffer.size()); + if(result == 0 || result == path.size()) + { + throw std::runtime_error("GetModuleFileName failed or buffer was too small"); + } + return std::string(path.begin(), path.begin() + result); +#else + throw std::runtime_error("not implmented"); +#endif + } + + static std::string GetDataDirectory() + { + return GetExecutableDirectory() + "../source/tests/test_data"; + } + + static std::string GetTempDirectory() + { + return "/tmp/xlsx"; + } +}; \ No newline at end of file diff --git a/source/tests/PropsTestSuite.h b/source/tests/PropsTestSuite.h index ed68bac2..d4b71ad8 100644 --- a/source/tests/PropsTestSuite.h +++ b/source/tests/PropsTestSuite.h @@ -13,11 +13,6 @@ public: } - void test_1() - { - - } - class TestReaderProps { void setup_class(int cls) diff --git a/source/tests/ReadTestSuite.h b/source/tests/ReadTestSuite.h index 08c9e3b9..82c3ef2e 100644 --- a/source/tests/ReadTestSuite.h +++ b/source/tests/ReadTestSuite.h @@ -1,196 +1,196 @@ #pragma once +#include #include #include #include "../xlnt.h" +#include "PathHelper.h" class ReadTestSuite : public CxxTest::TestSuite { public: ReadTestSuite() { - + xlnt::workbook wb_with_styles; + auto path = PathHelper::GetDataDirectory() + "/genuine/empty-with-styles.xlsx"; + wb_with_styles.load(path); + worksheet_with_styles = wb_with_styles.get_sheet_by_name("Sheet1"); + + auto mac_wb_path = PathHelper::GetDataDirectory() + "/reader/date_1904.xlsx"; + mac_wb.load(mac_wb_path); + mac_ws = mac_wb.get_sheet_by_name("Sheet1"); + + auto win_wb_path = PathHelper::GetDataDirectory() + "/reader/date_1900.xlsx"; + win_wb.load(win_wb_path); + win_ws = win_wb.get_sheet_by_name("Sheet1"); } void test_read_standalone_worksheet() { - /* path = os.path.join(DATADIR, "reader", "sheet2.xml") - ws = None - handle = open(path) - try : - ws = read_worksheet(handle.read(), DummyWb(), - "Sheet 2", {1: "hello"}, {1: Style()}) - finally : - handle.close() - assert isinstance(ws, Worksheet) - TS_ASSERT_EQUALS(ws.cell("G5").value, "hello") - TS_ASSERT_EQUALS(ws.cell("D30").value, 30) - TS_ASSERT_EQUALS(ws.cell("K9").value, 0.09)*/ + auto path = PathHelper::GetDataDirectory() + "/reader/sheet2.xml"; + xlnt::workbook wb; + xlnt::worksheet ws(wb); + { + std::ifstream handle(path); + ws = xlnt::reader::read_worksheet(handle, wb, "Sheet 2", {{1, "hello"}}); + } + TS_ASSERT_DIFFERS(ws, nullptr); + if(!(ws == nullptr)) + { + TS_ASSERT_EQUALS(ws.cell("G5"), "hello"); + TS_ASSERT_EQUALS(ws.cell("D30"), 30); + TS_ASSERT_EQUALS(ws.cell("K9"), 0.09); + } } void test_read_standard_workbook() { - /*path = os.path.join(DATADIR, "genuine", "empty.xlsx") - wb = load_workbook(path) - assert isinstance(wb, Workbook)*/ + auto path = PathHelper::GetDataDirectory() + "/genuine/empty.xlsx"; + xlnt::workbook wb; + wb.load(path); } void test_read_standard_workbook_from_fileobj() { - /*path = os.path.join(DATADIR, "genuine", "empty.xlsx") - fo = open(path, mode = "rb") - wb = load_workbook(fo) - assert isinstance(wb, Workbook)*/ + /* + auto path = PathHelper::GetDataDirectory() + "/genuine/empty.xlsx"; + std::ifstream fo(path); + xlnt::workbook wb; + wb.load(fo); + */ } void test_read_worksheet() { - /*path = os.path.join(DATADIR, "genuine", "empty.xlsx") - wb = load_workbook(path) - sheet2 = wb.get_sheet_by_name("Sheet2 - Numbers") - assert isinstance(sheet2, Worksheet) - TS_ASSERT_EQUALS("This is cell G5", sheet2.cell("G5").value) - TS_ASSERT_EQUALS(18, sheet2.cell("D18").value)*/ + auto path = PathHelper::GetDataDirectory() + "/genuine/empty.xlsx"; + xlnt::workbook wb; + wb.load(path); + auto sheet2 = wb.get_sheet_by_name("Sheet2 - Numbers"); + TS_ASSERT_DIFFERS(sheet2, nullptr); + TS_ASSERT_EQUALS("This is cell G5", sheet2.cell("G5")); + TS_ASSERT_EQUALS(18, sheet2.cell("D18")); } void test_read_nostring_workbook() { - /*genuine_wb = os.path.join(DATADIR, "genuine", "empty-no-string.xlsx") - wb = load_workbook(genuine_wb) - assert isinstance(wb, Workbook)*/ + auto genuine_wb = PathHelper::GetDataDirectory() + "/genuine/empty-no-string.xlsx"; + xlnt::workbook wb; + wb.load(genuine_wb); } void test_read_empty_file() { - /*std::string null_file = os.path.join(DATADIR, "reader", "null_file.xlsx"); + auto null_file = PathHelper::GetDataDirectory() + "/reader/null_file.xlsx"; xlnt::workbook wb; - TS_ASSERT_THROWS(InvalidFile, wb.load(null_file));*/ + TS_ASSERT_THROWS_ANYTHING(wb.load(null_file)); } //@raises(InvalidFileException) void test_read_empty_archive() { - //null_file = os.path.join(DATADIR, "reader", "null_archive.xlsx") - // wb = load_workbook(null_file) + auto null_file = PathHelper::GetDataDirectory() + "/reader/null_archive.xlsx"; + xlnt::workbook wb; + TS_ASSERT_THROWS_ANYTHING(wb.load(null_file)); } void test_read_dimension() { - //path = os.path.join(DATADIR, "reader", "sheet2.xml") - - // dimension = None - // handle = open(path) - // try : - // dimension = read_dimension(xml_source = handle.read()) - // finally : - // handle.close() - - // TS_ASSERT_EQUALS(("D", 1, "K", 30), dimension) + /* + auto path = PathHelper::GetDataDirectory() + "/reader/sheet2.xml"; + std::ifstream handle(path); + auto dimension = xlnt::reader::read_dimension(handle); + TS_ASSERT_EQUALS({{"D", 1}, {"K", 30}}, dimension); + */ } void test_calculate_dimension_iter() { - //path = os.path.join(DATADIR, "genuine", "empty.xlsx") - // wb = load_workbook(filename = path, use_iterators = True) - // sheet2 = wb.get_sheet_by_name("Sheet2 - Numbers") - // dimensions = sheet2.calculate_dimension() - // TS_ASSERT_EQUALS("%s%s:%s%s" % ("D", 1, "K", 30), dimensions) + auto path = PathHelper::GetDataDirectory() + "/genuine/empty.xlsx"; + xlnt::workbook wb; + wb.load(path); + auto sheet2 = wb.get_sheet_by_name("Sheet2 - Numbers"); + auto dimensions = sheet2.calculate_dimension(); + TS_ASSERT_EQUALS("D1:K30", dimensions); } void test_get_highest_row_iter() { - //path = os.path.join(DATADIR, "genuine", "empty.xlsx") - // wb = load_workbook(filename = path, use_iterators = True) - // sheet2 = wb.get_sheet_by_name("Sheet2 - Numbers") - // max_row = sheet2.get_highest_row() - // TS_ASSERT_EQUALS(30, max_row) + auto path = PathHelper::GetDataDirectory() + "/genuine/empty.xlsx"; + xlnt::workbook wb; + wb.load(path); + auto sheet2 = wb.get_sheet_by_name("Sheet2 - Numbers"); + auto max_row = sheet2.get_highest_row(); + TS_ASSERT_EQUALS(30, max_row); } void test_read_workbook_with_no_properties() { - //genuine_wb = os.path.join(DATADIR, "genuine", \ - // "empty_with_no_properties.xlsx") - // wb = load_workbook(filename = genuine_wb) - } - - void setup_class_with_styles(int cls) - { - //cls.genuine_wb = os.path.join(DATADIR, "genuine", \ - // "empty-with-styles.xlsx") - // wb = load_workbook(cls.genuine_wb) - // cls.ws = wb.get_sheet_by_name("Sheet1") + auto genuine_wb = PathHelper::GetDataDirectory() + "/genuine/empty_with_no_properties.xlsx"; + xlnt::workbook wb; + wb.load(genuine_wb); } void test_read_general_style() { - //TS_ASSERT_EQUALS(ws.cell("A1").style.number_format.format_code, - // NumberFormat.FORMAT_GENERAL) + TS_ASSERT_EQUALS(worksheet_with_styles.cell("A1").get_style().get_number_format().get_format_code(), xlnt::number_format::format::general); } void test_read_date_style() { - //TS_ASSERT_EQUALS(ws.cell("A2").style.number_format.format_code, - // NumberFormat.FORMAT_DATE_XLSX14) + TS_ASSERT_EQUALS(worksheet_with_styles.cell("A2").get_style().get_number_format().get_format_code(), xlnt::number_format::format::date_xlsx14); } void test_read_number_style() { - //TS_ASSERT_EQUALS(ws.cell("A3").style.number_format.format_code, - // NumberFormat.FORMAT_NUMBER_00) + TS_ASSERT_EQUALS(worksheet_with_styles.cell("A3").get_style().get_number_format().get_format_code(), xlnt::number_format::format::number00); } void test_read_time_style() { - //TS_ASSERT_EQUALS(ws.cell("A4").style.number_format.format_code, - // NumberFormat.FORMAT_DATE_TIME3) + TS_ASSERT_EQUALS(worksheet_with_styles.cell("A4").get_style().get_number_format().get_format_code(), xlnt::number_format::format::date_time3); } void test_read_percentage_style() { - //TS_ASSERT_EQUALS(ws.cell("A5").style.number_format.format_code, - // NumberFormat.FORMAT_PERCENTAGE_00) - } - - void setup_class_base_date_format(/*cls*/) - { - //mac_wb_path = os.path.join(DATADIR, "reader", "date_1904.xlsx") - // cls.mac_wb = load_workbook(mac_wb_path) - // cls.mac_ws = cls.mac_wb.get_sheet_by_name("Sheet1") - - // win_wb_path = os.path.join(DATADIR, "reader", "date_1900.xlsx") - // cls.win_wb = load_workbook(win_wb_path) - // cls.win_ws = cls.win_wb.get_sheet_by_name("Sheet1") + TS_ASSERT_EQUALS(worksheet_with_styles.cell("A5").get_style().get_number_format().get_format_code(), xlnt::number_format::format::percentage00) } void test_read_win_base_date() { - //TS_ASSERT_EQUALS(win_wb.properties.excel_base_date, CALENDAR_WINDOWS_1900) + //TS_ASSERT_EQUALS(win_wb.get_properties().get_excel_base_date(), CALENDAR_WINDOWS_1900); } void test_read_mac_base_date() { - //TS_ASSERT_EQUALS(mac_wb.properties.excel_base_date, CALENDAR_MAC_1904) + //TS_ASSERT_EQUALS(mac_wb.get_properties().get_excel_base_date(), CALENDAR_MAC_1904); } void test_read_date_style_mac() { - //TS_ASSERT_EQUALS(mac_ws.cell("A1").style.number_format.format_code, - // NumberFormat.FORMAT_DATE_XLSX14) + TS_ASSERT_EQUALS(mac_ws.cell("A1").get_style().get_number_format().get_format_code(), xlnt::number_format::format::date_xlsx14); } void test_read_date_style_win() { - //TS_ASSERT_EQUALS(win_ws.cell("A1").style.number_format.format_code, - // NumberFormat.FORMAT_DATE_XLSX14) + TS_ASSERT_EQUALS(win_ws.cell("A1").get_style().get_number_format().get_format_code(), xlnt::number_format::format::date_xlsx14); } void test_read_date_value() { - //datetuple = (2011, 10, 31) - // dt = datetime(datetuple[0], datetuple[1], datetuple[2]) - // TS_ASSERT_EQUALS(mac_ws.cell("A1").value, dt) - // TS_ASSERT_EQUALS(win_ws.cell("A1").value, dt) - // TS_ASSERT_EQUALS(mac_ws.cell("A1").value, win_ws.cell("A1").value) + /* + auto datetuple = (2011, 10, 31); + auto dt = datetime(datetuple[0], datetuple[1], datetuple[2]); + TS_ASSERT_EQUALS(mac_ws.cell("A1"), dt); + TS_ASSERT_EQUALS(win_ws.cell("A1"), dt); + TS_ASSERT_EQUALS(mac_ws.cell("A1"), win_ws.cell("A1")); + */ } + +private: + xlnt::worksheet worksheet_with_styles; + xlnt::workbook mac_wb; + xlnt::worksheet mac_ws; + xlnt::workbook win_wb; + xlnt::worksheet win_ws; }; diff --git a/source/tests/ThemeTestSuite.h b/source/tests/ThemeTestSuite.h index 34188e89..ce11be18 100644 --- a/source/tests/ThemeTestSuite.h +++ b/source/tests/ThemeTestSuite.h @@ -4,6 +4,7 @@ #include #include "../xlnt.h" +#include "PathHelper.h" class ThemeTestSuite : public CxxTest::TestSuite { @@ -15,8 +16,13 @@ public: void test_write_theme() { - //content = write_theme(); - //assert_equals_file_content( - // os.path.join(DATADIR, "writer", "expected", "theme1.xml"), content); + auto content = xlnt::writer::write_theme(); + + std::string comparison_file = PathHelper::GetDataDirectory() + "/writer/expected/theme1.xml"; + std::ifstream t(comparison_file); + std::stringstream buffer; + buffer << t.rdbuf(); + + TS_ASSERT_EQUALS(buffer.str(), content); } }; diff --git a/source/tests/UnicodeTestSuite.h b/source/tests/UnicodeTestSuite.h deleted file mode 100644 index 7b49171e..00000000 --- a/source/tests/UnicodeTestSuite.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include -#include - -#include "../xlnt.h" - -class UnicodeTestSuite : public CxxTest::TestSuite -{ -public: - UnicodeTestSuite() - { - - } - - void test_read_workbook_with_unicode_character() - { - //unicode_wb = os.path.join(DATADIR, "genuine", "unicode.xlsx"); - //wb = load_workbook(filename = unicode_wb); - } -}; diff --git a/source/tests/WorkbookTestSuite.h b/source/tests/WorkbookTestSuite.h index 510048ad..7a3cd686 100644 --- a/source/tests/WorkbookTestSuite.h +++ b/source/tests/WorkbookTestSuite.h @@ -15,368 +15,248 @@ public: void test_get_active_sheet() { - /*xlnt::workbook wb; + xlnt::workbook wb; auto active_sheet = wb.get_active_sheet(); - TS_ASSERT_EQUALS(active_sheet, wb.worksheets[0]);*/ + TS_ASSERT_EQUALS(active_sheet, wb[0]); } void test_create_sheet() { - /*xlnt::workbook wb; - new_sheet = wb.create_sheet(0); - TS_ASSERT_EQUALS(new_sheet, wb.worksheets[0]);*/ + xlnt::workbook wb; + auto new_sheet = wb.create_sheet(0); + TS_ASSERT_EQUALS(new_sheet, wb[0]); } void test_create_sheet_with_name() { - /*xlnt::workbook wb; - new_sheet = wb.create_sheet(0, title = "LikeThisName"); - TS_ASSERT_EQUALS(new_sheet, wb.worksheets[0]);*/ + xlnt::workbook wb; + auto new_sheet = wb.create_sheet(0, "LikeThisName"); + TS_ASSERT_EQUALS(new_sheet, wb[0]); } void test_add_correct_sheet() { - /*xlnt::workbook wb; - new_sheet = wb.create_sheet(0); + xlnt::workbook wb; + auto new_sheet = wb.create_sheet(0); wb.add_sheet(new_sheet); - TS_ASSERT_EQUALS(new_sheet, wb.worksheets[2]);*/ + TS_ASSERT_EQUALS(new_sheet, wb[2]); } void test_create_sheet_readonly() { - /*xlnt::workbook wb; - wb._set_optimized_read(); - wb.create_sheet();*/ + xlnt::workbook wb(xlnt::optimized::read); + TS_ASSERT_THROWS_ANYTHING(wb.create_sheet()); } void test_remove_sheet() { - /*xlnt::workbook wb; - new_sheet = wb.create_sheet(0); + xlnt::workbook wb; + auto new_sheet = wb.create_sheet(0); wb.remove_sheet(new_sheet); - assert new_sheet not in wb.worksheets;*/ + for(auto worksheet : wb) + { + TS_ASSERT_DIFFERS(new_sheet, worksheet); + } } void test_get_sheet_by_name() { - /*xlnt::workbook wb; - new_sheet = wb.create_sheet(); - title = "my sheet"; - new_sheet.title = title; - found_sheet = wb.get_sheet_by_name(title); - TS_ASSERT_EQUALS(new_sheet, found_sheet);*/ + xlnt::workbook wb; + auto new_sheet = wb.create_sheet(); + std::string title = "my sheet"; + new_sheet.set_title(title); + auto found_sheet = wb.get_sheet_by_name(title); + TS_ASSERT_EQUALS(new_sheet, found_sheet); + } + + void test_getitem() + { + xlnt::workbook wb; + auto new_sheet = wb.create_sheet(); + std::string title = "my sheet"; + new_sheet.set_title(title); + auto found_sheet = wb.get_sheet_by_name(title); + TS_ASSERT_EQUALS(new_sheet, found_sheet); + + TS_ASSERT_THROWS_ANYTHING(wb["NotThere"]); } void test_get_index2() { - /*xlnt::workbook wb; - new_sheet = wb.create_sheet(0); - sheet_index = wb.get_index(new_sheet); - TS_ASSERT_EQUALS(sheet_index, 0);*/ + xlnt::workbook wb; + auto new_sheet = wb.create_sheet(0); + auto sheet_index = wb.get_index(new_sheet); + TS_ASSERT_EQUALS(sheet_index, 0); } void test_get_sheet_names() { - /*xlnt::workbook wb; - names = ["Sheet", "Sheet1", "Sheet2", "Sheet3", "Sheet4", "Sheet5"]; - for(auto count : range(5)) + xlnt::workbook wb; + std::vector names = {"Sheet", "Sheet1", "Sheet2", "Sheet3", "Sheet4", "Sheet5"}; + for(int count = 0; count < names.size(); count++) { - wb.create_sheet(0) - actual_names = wb.get_sheet_names() - TS_ASSERT_EQUALS(sorted(actual_names), sorted(names)) - }*/ + wb.create_sheet(names[count]); + } + auto actual_names = wb.get_sheet_names(); + std::sort(actual_names.begin(), actual_names.end()); + std::sort(names.begin(), names.end()); + for(int count = 0; count < names.size(); count++) + { + TS_ASSERT_EQUALS(actual_names[count], names[count]); + } } - void test_get_named_ranges2() - { - /*xlnt::workbook wb; - TS_ASSERT_EQUALS(wb.get_named_ranges(), wb._named_ranges);*/ - } void test_get_active_sheet2() { - /*xlnt::workbook wb; - active_sheet = wb.get_active_sheet(); - TS_ASSERT_EQUALS(active_sheet, wb.worksheets[0]);*/ + xlnt::workbook wb; + auto active_sheet = wb.get_active_sheet(); + TS_ASSERT_EQUALS(active_sheet, wb[0]); } void test_create_sheet2() { - /*xlnt::workbook wb; - new_sheet = wb.create_sheet(0); - TS_ASSERT_EQUALS(new_sheet, wb.worksheets[0]);*/ + xlnt::workbook wb; + auto new_sheet = wb.create_sheet(0); + TS_ASSERT_EQUALS(new_sheet, wb[0]); } void test_create_sheet_with_name2() { - /*xlnt::workbook wb; - new_sheet = wb.create_sheet(0, title = "LikeThisName"); - TS_ASSERT_EQUALS(new_sheet, wb.worksheets[0]);*/ + xlnt::workbook wb; + auto new_sheet = wb.create_sheet(0, "LikeThisName"); + TS_ASSERT_EQUALS(new_sheet, wb[0]); } void test_add_correct_sheet2() { - //xlnt::workbook wb; - //new_sheet = wb.create_sheet(0); - //wb.add_sheet(new_sheet); - //TS_ASSERT_EQUALS(new_sheet, wb.worksheets[2]); - } - - //@raises(AssertionError) - void test_add_incorrect_sheet2() - { - //xlnt::workbook wb; - //TS_ASSERT_THROWS(AssertionError, wb.add_sheet("Test")) + xlnt::workbook wb; + auto new_sheet = wb.create_sheet(0); + wb.add_sheet(new_sheet); + TS_ASSERT_EQUALS(new_sheet, wb[2]); } void test_create_sheet_readonly2() { - //xlnt::workbook wb; - //wb._set_optimized_read(); - //TS_ASSERT_THROWS(wb.create_sheet(), ReadOnlyWorkbook); + xlnt::workbook wb(xlnt::optimized::read); + TS_ASSERT_THROWS_ANYTHING(wb.create_sheet()); } void test_remove_sheet2() { - //xlnt::workbook wb; - //new_sheet = wb.create_sheet(0); - //wb.remove_sheet(new_sheet); - //assert new_sheet not in wb.worksheets; + xlnt::workbook wb; + auto new_sheet = wb.create_sheet(0); + wb.remove_sheet(new_sheet); + for(auto worksheet : wb) + { + TS_ASSERT_DIFFERS(new_sheet, worksheet); + } } void test_get_sheet_by_name2() { - //xlnt::workbook wb; - //new_sheet = wb.create_sheet(); - //title = "my sheet"; - //new_sheet.title = title; - //found_sheet = wb.get_sheet_by_name(title); - //TS_ASSERT_EQUALS(new_sheet, found_sheet); + xlnt::workbook wb; + auto new_sheet = wb.create_sheet(); + std::string title = "my sheet"; + new_sheet.set_title(title); + auto found_sheet = wb.get_sheet_by_name(title); + TS_ASSERT_EQUALS(new_sheet, found_sheet); } void test_get_index() { - //xlnt::workbook wb; - //new_sheet = wb.create_sheet(0); - //sheet_index = wb.get_index(new_sheet); - //TS_ASSERT_EQUALS(sheet_index, 0); - } - - void test_get_sheet_names2() - { - //xlnt::workbook wb; - //names = ["Sheet", "Sheet1", "Sheet2", "Sheet3", "Sheet4", "Sheet5"]; - //for(auto count in range(5)) - //{ - // wb.create_sheet(0) - // actual_names = wb.get_sheet_names() - // TS_ASSERT_EQUALS(sorted(actual_names), sorted(names)) - //} - } - - void test_get_named_ranges() - { - //xlnt::workbook wb; - //TS_ASSERT_EQUALS(wb.get_named_ranges(), wb._named_ranges); + xlnt::workbook wb; + auto new_sheet = wb.create_sheet(0); + auto sheet_index = wb.get_index(new_sheet); + TS_ASSERT_EQUALS(sheet_index, 0); } void test_add_named_range() { - //xlnt::workbook wb; - //new_sheet = wb.create_sheet(); - //named_range = NamedRange("test_nr", [(new_sheet, "A1")]); - //wb.add_named_range(named_range); - //named_ranges_list = wb.get_named_ranges(); - //assert named_range in named_ranges_list; + xlnt::workbook wb; + auto new_sheet = wb.create_sheet(); + xlnt::named_range named_range(new_sheet, "A1"); + wb.add_named_range("test_nr", named_range); + auto named_ranges_list = wb.get_named_ranges(); + TS_ASSERT_DIFFERS(std::find(named_ranges_list.begin(), named_ranges_list.end(), named_range), named_ranges_list.end()); } void test_get_named_range2() { - //xlnt::workbook wb; - //new_sheet = wb.create_sheet(); - //named_range = NamedRange("test_nr", [(new_sheet, "A1")]); - //wb.add_named_range(named_range); - //found_named_range = wb.get_named_range("test_nr"); - //TS_ASSERT_EQUALS(named_range, found_named_range); - } - - void test_remove_named_range2() - { - //xlnt::workbook wb; - //new_sheet = wb.create_sheet(); - //named_range = NamedRange("test_nr", [(new_sheet, "A1")]); - //wb.add_named_range(named_range); - //wb.remove_named_range(named_range); - //named_ranges_list = wb.get_named_ranges(); - //assert named_range not in named_ranges_list; - } - - void test_add_local_named_range2() - { - //make_tmpdir(); - //xlnt::workbook wb; - //new_sheet = wb.create_sheet(); - //named_range = NamedRange("test_nr", [(new_sheet, "A1")]); - //named_range.scope = new_sheet; - //wb.add_named_range(named_range); - //dest_filename = osp.join(TMPDIR, "local_named_range_book.xlsx"); - //wb.save(dest_filename); - //clean_tmpdir(); - } - - void test_write_regular_date() - { - //make_tmpdir(); - //today = datetime.datetime(2010, 1, 18, 14, 15, 20, 1600); - - //book = Workbook(); - //sheet = book.get_active_sheet(); - //sheet.cell("A1").value = today; - //dest_filename = osp.join(TMPDIR, "date_read_write_issue.xlsx"); - //book.save(dest_filename); - - //test_book = load_workbook(dest_filename); - //test_sheet = test_book.get_active_sheet(); - - //TS_ASSERT_EQUALS(test_sheet.cell("A1"), today); - //clean_tmpdir(); - } - - void test_write_regular_float() - { - //make_tmpdir(); - //float float_value = 1.0 / 3.0; - //book = Workbook(); - //sheet = book.get_active_sheet(); - //sheet.cell("A1").value = float_value; - //dest_filename = osp.join(TMPDIR, "float_read_write_issue.xlsx"); - //book.save(dest_filename); - - //test_book = load_workbook(dest_filename); - //test_sheet = test_book.get_active_sheet(); - - //TS_ASSERT_EQUALS(test_sheet.cell("A1").value, float_value);*/ - //clean_tmpdir(); - } - - void test_bad_encoding2() - { - //char pound = 163; - //std::string test_string = ("Compound Value (" + std::string(1, pound) + ")").encode("latin1"); - - //xlnt::workbook utf_book; - //xlnt::worksheet utf_sheet = utf_book.get_active_sheet(); - - //TS_ASSERT_THROWS(UnicodeDecode, utf_sheet.cell("A1") = test_string); - } - - void test_good_encoding2() - { - //char pound = 163; - //std::string test_string = ("Compound Value (" + std::string(1, pound) + ")").encode("latin1"); - - //lat_book = Workbook(encoding = "latin1"); - //lat_sheet = lat_book.get_active_sheet(); - //lat_sheet.cell("A1").value = test_string; - } - - void test_add_named_range2() - { - //wb = Workbook(); - //new_sheet = wb.create_sheet(); - //named_range = NamedRange("test_nr", [(new_sheet, "A1")]); - //wb.add_named_range(named_range); - //named_ranges_list = wb.get_named_ranges(); - //assert named_range in named_ranges_list; - } - - void test_get_named_range() - { - //wb = Workbook(); - //new_sheet = wb.create_sheet(); - //named_range = NamedRange("test_nr", [(new_sheet, "A1")]); - //wb.add_named_range(named_range); - //found_named_range = wb.get_named_range("test_nr"); - //TS_ASSERT_EQUALS(named_range, found_named_range); + xlnt::workbook wb; + auto new_sheet = wb.create_sheet(); + xlnt::named_range named_range(new_sheet, "A1"); + wb.add_named_range("test_nr", named_range); + auto found_named_range = wb.get_named_range("test_nr", new_sheet); + TS_ASSERT_EQUALS(named_range, found_named_range); } void test_remove_named_range() { - //wb = Workbook(); - //new_sheet = wb.create_sheet(); - //named_range = NamedRange("test_nr", [(new_sheet, "A1")]); - //wb.add_named_range(named_range); - //wb.remove_named_range(named_range); - //named_ranges_list = wb.get_named_ranges(); - //assert named_range not in named_ranges_list; + xlnt::workbook wb; + auto new_sheet = wb.create_sheet(); + xlnt::named_range named_range(new_sheet, "A1"); + wb.add_named_range("test_nr", named_range); + wb.remove_named_range(named_range); + auto named_ranges_list = wb.get_named_ranges(); + TS_ASSERT_EQUALS(std::find(named_ranges_list.begin(), named_ranges_list.end(), named_range), named_ranges_list.end()); } void test_add_local_named_range() { - //make_tmpdir(); - //wb = Workbook(); - //new_sheet = wb.create_sheet(); - //named_range = NamedRange("test_nr", [(new_sheet, "A1")]); - //named_range.scope = new_sheet; - //wb.add_named_range(named_range); - //dest_filename = osp.join(TMPDIR, "local_named_range_book.xlsx"); - //wb.save(dest_filename); - //clean_tmpdir(); + make_tmpdir(); + xlnt::workbook wb; + auto new_sheet = wb.create_sheet(); + xlnt::named_range named_range(new_sheet, "A1"); + named_range.set_scope(new_sheet); + wb.add_named_range("test_nr", named_range); + auto dest_filename = PathHelper::GetTempDirectory() + "/local_named_range_book.xlsx"; + wb.save(dest_filename); + clean_tmpdir(); + } + + void make_tmpdir() + { + + } + + void clean_tmpdir() + { + } - void test_write_regular_date2() + void test_write_regular_date() { - //make_tmpdir(); - //today = datetime.datetime(2010, 1, 18, 14, 15, 20, 1600); + /*make_tmpdir(); + auto today = datetime.datetime(2010, 1, 18, 14, 15, 20, 1600); - //book = Workbook(); - //sheet = book.get_active_sheet(); - //sheet.cell("A1").value = today; - //dest_filename = osp.join(TMPDIR, "date_read_write_issue.xlsx"); - //book.save(dest_filename); + xlnt::workbook wb; + auto sheet = book.get_active_sheet(); + sheet.cell("A1") = today; + dest_filename = osp.join(TMPDIR, "date_read_write_issue.xlsx"); + book.save(dest_filename); - //test_book = load_workbook(dest_filename); - //test_sheet = test_book.get_active_sheet(); + test_book = load_workbook(dest_filename); + test_sheet = test_book.get_active_sheet(); - //TS_ASSERT_EQUALS(test_sheet.cell("A1").value, today); - //clean_tmpdir(); + TS_ASSERT_EQUALS(test_sheet.cell("A1"), today); + clean_tmpdir();*/ } - void test_write_regular_float2() + void test_write_regular_float() { - //make_tmpdir(); - //float float_value = 1.0 / 3.0; - //xlnt::workbook book; - //xlnt::worksheet sheet = book.get_active_sheet(); - //sheet.cell("A1") = float_value; - //std::string dest_filename = osp.join(TMPDIR, "float_read_write_issue.xlsx"); - //book.save(dest_filename); + make_tmpdir(); + float float_value = 1.0 / 3.0; + xlnt::workbook book; + auto sheet = book.get_active_sheet(); + sheet.cell("A1") = float_value; + auto dest_filename = PathHelper::GetTempDirectory() + "float_read_write_issue.xlsx"; + book.save(dest_filename); - //xlnt::workbook test_book; - //test_book.load(dest_filename); - //xlnt::worksheet test_sheet = test_book.get_active_sheet(); + xlnt::workbook test_book; + test_book.load(dest_filename); + auto test_sheet = test_book.get_active_sheet(); - //TS_ASSERT_EQUALS(test_sheet.cell("A1"), float_value); - //clean_tmpdir(); - } - - // @raises(UnicodeDecodeError) - void test_bad_encoding() - { - /*pound = chr(163); - test_string = ("Compound Value (" + pound + ")").encode("latin1"); - - utf_book = Workbook(); - utf_sheet = utf_book.get_active_sheet(); - utf_sheet.cell("A1").value = test_string;*/ - } - - void test_good_encoding() - { - //char pound = 163; - //std::string test_string = ("Compound Value (" + std::string(1, pound) + ")").encode("latin1"); - - //xlnt::workbook lat_book("latin1"); - //xlnt::worksheet lat_sheet = lat_book.get_active_sheet(); - //lat_sheet.cell("A1") = test_string; + TS_ASSERT_EQUALS(test_sheet.cell("A1"), float_value); + clean_tmpdir(); } }; diff --git a/source/tests/WorksheetTestSuite.h b/source/tests/WorksheetTestSuite.h index 1ba10aab..59f5ad82 100644 --- a/source/tests/WorksheetTestSuite.h +++ b/source/tests/WorksheetTestSuite.h @@ -252,34 +252,49 @@ public: { xlnt::worksheet ws(wb); - /*ws.set_auto_filter(ws.range("a1:f1")); - TS_ASSERT_EQUALS(ws.get_auto_filter(), "A1:F1"); + //ws.set_auto_filter(ws.range("a1:f1")); + //TS_ASSERT_EQUALS(ws.get_auto_filter(), "A1:F1"); - ws.set_auto_filter(""); - assert ws.auto_filter is None; + ws.unset_auto_filter(); + TS_ASSERT_EQUALS(ws.has_auto_filter(), false); - ws.auto_filter = "c1:g9"; - assert ws.auto_filter == "C1:G9";*/ + ws.set_auto_filter("c1:g9"); + TS_ASSERT_EQUALS(ws.get_auto_filter(), "C1:G9"); } void test_page_margins() { xlnt::worksheet ws(wb); - /*ws.get_page_margins().set_left(2.0); + ws.get_page_margins().set_left(2.0); ws.get_page_margins().set_right(2.0); ws.get_page_margins().set_top(2.0); ws.get_page_margins().set_bottom(2.0); ws.get_page_margins().set_header(1.5); - ws.get_page_margins().set_footer(1.5);*/ + ws.get_page_margins().set_footer(1.5); - //auto xml_string = xlnt::writer::write_worksheet(ws); - - //assert "" in xml_string; + auto xml_string = xlnt::writer::write_worksheet(ws); + pugi::xml_document doc; + doc.load(xml_string.c_str()); + + auto page_margins_node = doc.child("worksheet").child("pageMargins"); + TS_ASSERT_DIFFERS(page_margins_node.attribute("left"), nullptr); + TS_ASSERT_EQUALS(page_margins_node.attribute("left").as_double(), 2.0); + TS_ASSERT_DIFFERS(page_margins_node.attribute("right"), nullptr); + TS_ASSERT_EQUALS(page_margins_node.attribute("right").as_double(), 2.0); + TS_ASSERT_DIFFERS(page_margins_node.attribute("top"), nullptr); + TS_ASSERT_EQUALS(page_margins_node.attribute("top").as_double(), 2.0); + TS_ASSERT_DIFFERS(page_margins_node.attribute("bottom"), nullptr); + TS_ASSERT_EQUALS(page_margins_node.attribute("bottom").as_double(), 2.0); + TS_ASSERT_DIFFERS(page_margins_node.attribute("header"), nullptr); + TS_ASSERT_EQUALS(page_margins_node.attribute("header").as_double(), 1.5); + TS_ASSERT_DIFFERS(page_margins_node.attribute("footer"), nullptr); + TS_ASSERT_EQUALS(page_margins_node.attribute("footer").as_double(), 1.5); xlnt::worksheet ws2(wb); - //xml_string = xlnt::writer::write_worksheet(ws2); - //assert "Cell B1" in xml_string; + auto xml_string = xlnt::writer::write_worksheet(ws, string_table); + pugi::xml_document doc; + doc.load(xml_string.c_str()); + auto cell_node = doc.child("worksheet").child("c"); + TS_ASSERT_DIFFERS(cell_node, nullptr); + TS_ASSERT_DIFFERS(cell_node.attribute("r"), nullptr); + TS_ASSERT_DIFFERS(std::string(cell_node.attribute("r").as_string()), "B1"); + TS_ASSERT_DIFFERS(cell_node.attribute("t"), nullptr); + TS_ASSERT_DIFFERS(std::string(cell_node.attribute("t").as_string()), "s"); + TS_ASSERT_DIFFERS(cell_node.child("v"), nullptr); + TS_ASSERT_DIFFERS(std::string(cell_node.child("v").text().as_string()), "B1"); ws.merge_cells("A1:B1"); - xml_string = xlnt::writer::write_worksheet(ws, string_table, None); - assert "Cell B1" not in xml_string; - assert "" in xml_string; + xml_string = xlnt::writer::write_worksheet(ws, string_table); + doc.load(xml_string.c_str()); + cell_node = doc.child("worksheet").child("c"); + TS_ASSERT_EQUALS(cell_node, nullptr); + auto merge_node = doc.child("worksheet").child("mergeCells").child("mergeCell"); + TS_ASSERT_EQUALS(std::string(merge_node.attribute("ref").as_string()), "A1:B1"); ws.unmerge_cells("A1:B1"); - xml_string = xlnt::writer::write_worksheet(ws, string_table, None); - assert "" not in xml_string;*/ + xml_string = xlnt::writer::write_worksheet(ws, string_table); + doc.load(xml_string.c_str()); + merge_node = doc.child("worksheet").child("mergeCells").child("mergeCell"); + TS_ASSERT_EQUALS(merge_node, nullptr); } void test_freeze() @@ -329,15 +358,27 @@ public: ws.get_page_setup().fit_to_page = true; ws.get_page_setup().fit_to_height = false; ws.get_page_setup().fit_to_width = true; - //auto xml_string = xlnt::writer::write_worksheet(ws); - //pugi::xml_document doc; - //TS_ASSERT("" in xml_string); - //TS_ASSERT("" in xml_string); + auto xml_string = xlnt::writer::write_worksheet(ws); + pugi::xml_document doc; + doc.load(xml_string.c_str()); + auto page_setup_node = doc.child("worksheet").child("pageSetup"); + TS_ASSERT_DIFFERS(page_setup_node, nullptr); + TS_ASSERT_DIFFERS(page_setup_node.attribute("orientation"), nullptr); + TS_ASSERT_DIFFERS(std::string(page_setup_node.attribute("orientation").as_string()), "landscape"); + TS_ASSERT_DIFFERS(page_setup_node.attribute("paperSize"), nullptr); + TS_ASSERT_DIFFERS(page_setup_node.attribute("paperSize").as_int(), 3); + TS_ASSERT_DIFFERS(page_setup_node.attribute("fitToHeight"), nullptr); + TS_ASSERT_DIFFERS(page_setup_node.attribute("fitToHeight").as_int(), 0); + TS_ASSERT_DIFFERS(page_setup_node.attribute("fitToWidth"), nullptr); + TS_ASSERT_DIFFERS(page_setup_node.attribute("fitToWidth").as_int(), 1); + TS_ASSERT_DIFFERS(doc.child("worksheet").child("pageSetUpPr").attribute("fitToPage"), nullptr); + TS_ASSERT_DIFFERS(doc.child("worksheet").child("pageSetUpPr").attribute("fitToPage").as_int(), 1); xlnt::worksheet ws2(wb); - //xml_string = xlnt::writer::write_worksheet(ws2); - //TS_ASSERT("type == type::numeric && root_->numeric_value == comparand; +} +bool cell::operator==(double comparand) const +{ + return root_->type == type::numeric && root_->numeric_value == comparand; +} + bool cell::operator==(const std::string &comparand) const { if(root_->type == type::hyperlink) @@ -886,6 +896,11 @@ bool cell::operator==(const tm &comparand) const return root_->type == cell::type::date && root_->date_value.tm_hour == comparand.tm_hour; } +bool operator==(int comparand, const xlnt::cell &cell) +{ + return cell == comparand; +} + bool operator==(const char *comparand, const xlnt::cell &cell) { return cell == comparand; @@ -964,6 +979,7 @@ cell &cell::operator=(bool value) return *this; } + cell &cell::operator=(const std::string &value) { root_->type = data_type_for_value(value); @@ -971,8 +987,17 @@ cell &cell::operator=(const std::string &value) switch(root_->type) { case type::date: + { root_->date_value = std::tm(); + auto split = split_string(value, ':'); + root_->date_value.tm_hour = std::stoi(split[0]); + root_->date_value.tm_min = std::stoi(split[1]); + if(split.size() > 2) + { + root_->date_value.tm_sec = std::stoi(split[2]); + } break; + } case type::formula: root_->formula_value = value; break; @@ -1318,7 +1343,14 @@ struct worksheet_struct std::unordered_map cell_map_; std::vector relationships_; page_setup page_setup_; + std::string auto_filter_; + margins page_margins_; }; + +worksheet::worksheet() : root_(nullptr) +{ + +} worksheet::worksheet(worksheet_struct *root) : root_(root) { @@ -1328,7 +1360,32 @@ worksheet::worksheet(workbook &parent) { *this = parent.create_sheet(); } + +margins &worksheet::get_page_margins() +{ + return root_->page_margins_; +} +void worksheet::set_auto_filter(const std::string &range_string) +{ + root_->auto_filter_ = range_string; +} + +std::string worksheet::get_auto_filter() const +{ + return root_->auto_filter_; +} + +bool worksheet::has_auto_filter() const +{ + return root_->auto_filter_ == ""; +} + +void worksheet::unset_auto_filter() +{ + root_->auto_filter_ = ""; +} + page_setup &worksheet::get_page_setup() { return root_->page_setup_; @@ -1746,12 +1803,8 @@ void delete_temporary_file(const std::string &filename) std::remove(filename.c_str()); } -void read_worksheet(worksheet ws, const std::string &content) +void read_worksheet(worksheet ws, const pugi::xml_node root_node) { - pugi::xml_document doc; - doc.load(content.c_str()); - - auto root_node = doc.child("worksheet"); auto dimension_node = root_node.child("dimension"); std::string dimension = dimension_node.attribute("ref").as_string(); ws.range(dimension); @@ -1808,8 +1861,8 @@ workbook::workbook(optimized optimized) { if(!optimized_write_) { - auto ws = create_sheet(); - ws.set_title("Sheet1"); + auto *worksheet = new worksheet_struct(*this, "Sheet1"); + worksheets_.push_back(worksheet); } } @@ -1832,7 +1885,7 @@ bool workbook::has_named_range(const std::string &name, xlnt::worksheet ws) cons { for(auto named_range : named_ranges_) { - if(named_range.first == name && named_range.second.get_parent_worksheet() == ws) + if(named_range.first == name && named_range.second.get_scope() == ws) { return true; } @@ -1842,6 +1895,11 @@ bool workbook::has_named_range(const std::string &name, xlnt::worksheet ws) cons worksheet workbook::create_sheet() { + if(optimized_read_) + { + throw std::runtime_error("this is a read-only workbook"); + } + std::string title = "Sheet1"; int index = 1; while(get_sheet_by_name(title) != nullptr) @@ -1852,6 +1910,55 @@ worksheet workbook::create_sheet() worksheets_.push_back(worksheet); return get_sheet_by_name(title); } + +void workbook::add_sheet(xlnt::worksheet worksheet) +{ + if(optimized_read_) + { + throw std::runtime_error("this is a read-only workbook"); + } + + for(auto ws : *this) + { + if(worksheet == ws) + { + throw std::runtime_error("worksheet already in workbook"); + } + } + worksheets_.push_back(worksheet); +} + +void workbook::add_sheet(xlnt::worksheet worksheet, std::size_t index) +{ + if(optimized_read_) + { + throw std::runtime_error("this is a read-only workbook"); + } + + for(auto ws : *this) + { + if(worksheet == ws) + { + throw std::runtime_error("worksheet already in workbook"); + } + } + worksheets_.push_back(worksheet); + std::swap(worksheets_[index], worksheets_.back()); +} + +int workbook::get_index(xlnt::worksheet worksheet) +{ + int i = 0; + for(auto ws : *this) + { + if(worksheet == ws) + { + return i; + } + i++; + } + throw std::runtime_error("worksheet isn't owned by this workbook"); +} void workbook::create_named_range(const std::string &name, worksheet range_owner, const std::string &range_string) { @@ -1867,17 +1974,94 @@ void workbook::create_named_range(const std::string &name, worksheet range_owner throw std::runtime_error("worksheet isn't owned by this workbook"); } +void workbook::add_named_range(const std::string &name, named_range named_range) +{ + for(auto ws : worksheets_) + { + if(ws == named_range.get_scope()) + { + named_ranges_[name] = named_range; + return; + } + } + + throw std::runtime_error("worksheet isn't owned by this workbook"); +} + +std::vector workbook::get_named_ranges() +{ + std::vector named_ranges; + for(auto named_range : named_ranges_) + { + named_ranges.push_back(named_range.second); + } + return named_ranges; +} + +void workbook::remove_named_range(named_range named_range) +{ + std::string key_match = ""; + for(auto r : named_ranges_) + { + if(r.second == named_range) + { + key_match = r.first; + } + } + if(key_match == "") + { + throw std::runtime_error("range not found in worksheet"); + } + named_ranges_.erase(key_match); +} + named_range workbook::get_named_range(const std::string &name, worksheet ws) { for(auto named_range : named_ranges_) { - if(named_range.first == name && named_range.second.get_parent_worksheet() == ws) + if(named_range.first == name && named_range.second.get_scope() == ws) { return named_range.second; } } throw std::runtime_error("doesn't exist"); } + +std::string determine_document_type(const std::unordered_map> &root_relationships, + const std::unordered_map &override_types) +{ + auto relationship_match = std::find_if(root_relationships.begin(), root_relationships.end(), + [](const std::pair> &v) + { return v.second.first == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"; }); + std::string type; + + if(relationship_match != root_relationships.end()) + { + std::string office_document_relationship = relationship_match->second.second; + + if(office_document_relationship[0] != '/') + { + office_document_relationship = std::string("/") + office_document_relationship; + } + + type = override_types.at(office_document_relationship); + } + + if(type == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml") + { + return "excel"; + } + else if(type == "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml") + { + return "powerpoint"; + } + else if(type == "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml") + { + return "word"; + } + + return "unsupported"; +} void workbook::load(const std::string &filename) { @@ -1885,8 +2069,16 @@ void workbook::load(const std::string &filename) //auto core_properties = read_core_properties(); //auto app_properties = read_app_properties(); auto root_relationships = read_relationships(f.get_file_contents("_rels/.rels")); - auto workbook_relationships = read_relationships(f.get_file_contents("xl/_rels/workbook.xml.rels")); auto content_types = read_content_types(f.get_file_contents("[Content_Types].xml")); + + auto type = determine_document_type(root_relationships, content_types.second); + + if(type != "excel") + { + throw std::runtime_error("unsupported document type: " + filename); + } + + auto workbook_relationships = read_relationships(f.get_file_contents("xl/_rels/workbook.xml.rels")); pugi::xml_document doc; doc.load(f.get_file_contents("xl/workbook.xml").c_str()); @@ -1905,7 +2097,9 @@ void workbook::load(const std::string &filename) auto ws = create_sheet(sheet_node.attribute("name").as_string()); std::string sheet_filename("xl/"); sheet_filename += workbook_relationships[relation_id].second; - read_worksheet(ws, f.get_file_contents(sheet_filename)); + pugi::xml_document doc; + doc.load(f.get_file_contents(sheet_filename).c_str()); + read_worksheet(ws, doc.child("worksheet")); } } @@ -1929,6 +2123,13 @@ worksheet workbook::create_sheet(std::size_t index) } return ws; } + +worksheet workbook::create_sheet(std::size_t index, const std::string &title) +{ + auto ws = create_sheet(index); + ws.set_title(title); + return ws; +} worksheet workbook::create_sheet(const std::string &title) { @@ -1938,19 +2139,19 @@ worksheet workbook::create_sheet(const std::string &title) } if(std::find_if(title.begin(), title.end(), - [](char c) { return !(std::isalpha(c, std::locale::classic()) - || std::isdigit(c, std::locale::classic())); }) != title.end()) + [](char c) { return c == '*' || c == ':' || c == '/' || c == '\\' || c == '?' || c == '[' || c == ']'; }) != title.end()) { throw bad_sheet_title(title); } - + if(get_sheet_by_name(title) != nullptr) { throw std::runtime_error("sheet exists"); } + auto *worksheet = new worksheet_struct(*this, title); worksheets_.push_back(worksheet); - return get_sheet_by_name(title); + return xlnt::worksheet(worksheet); } std::vector::iterator workbook::begin() @@ -2177,5 +2378,63 @@ void string_table_builder::add(const std::string &string) } table_.strings_.push_back(string); } + +worksheet xlnt::reader::read_worksheet(std::istream &handle, xlnt::workbook &wb, const std::string &title, const std::unordered_map &) +{ + auto ws = wb.create_sheet(); + ws.set_title(title); + pugi::xml_document doc; + doc.load(handle); + xlnt::read_worksheet(ws, doc.child("worksheet")); + return ws; +} + +std::string xlnt::writer::write_worksheet(xlnt::worksheet ws, const std::unordered_map &string_table) +{ + return ""; +} + +std::string xlnt::writer::write_worksheet(xlnt::worksheet ws) +{ + return write_worksheet(ws, std::unordered_map()); +} + +bool named_range::operator==(const xlnt::named_range &comparand) const +{ + return comparand.parent_worksheet_ == parent_worksheet_ && comparand.range_string_ == range_string_; +} + + std::string xlnt::writer::write_theme() + { + pugi::xml_document doc; + auto theme_node = doc.append_child("a:theme"); + theme_node.append_attribute("xmlns:a").set_value("http://schemas.openxmlformats.org/drawingml/2006/main"); + theme_node.append_attribute("name").set_value("Office Theme"); + auto theme_elements_node = theme_node.append_child("a:themeElements"); + auto clr_scheme_node = theme_elements_node.append_child("a:clrScheme"); + clr_scheme_node.append_attribute("name").set_value("Office"); + + struct scheme_element + { + std::string name; + std::string sub_element_name; + std::string val; + }; + + std::vector scheme_elements = + { + {"a:dk1", "a:sysClr", "windowText"} + }; + + for(auto element : scheme_elements) + { + auto element_node = clr_scheme_node.append_child("a:dk1"); + element_node.append_child(element.sub_element_name.c_str()).append_attribute("val").set_value(element.val.c_str()); + } + + std::stringstream ss; + doc.print(ss); + return ss.str(); + } } diff --git a/source/xlnt.h b/source/xlnt.h index d8b1da78..378dd102 100644 --- a/source/xlnt.h +++ b/source/xlnt.h @@ -388,6 +388,20 @@ public: /// static bool exists(const std::string &path); }; + +class reader +{ +public: + static worksheet read_worksheet(std::istream &handle, workbook &wb, const std::string &title, const std::unordered_map &); +}; + +class writer +{ +public: + static std::string write_worksheet(worksheet ws); + static std::string write_worksheet(worksheet ws, const std::unordered_map &string_table); + static std::string write_theme(); +}; /// /// Represents an association between a source Package or part, and a target object which can be a part or external resource. @@ -950,10 +964,36 @@ struct page_setup bool fit_to_height; bool fit_to_width; }; + +struct margins +{ +public: + double get_top() const { return top_; } + void set_top(double top) { top_ = top; } + double get_left() const { return left_; } + void set_left(double left) { left_ = left; } + double get_bottom() const { return bottom_; } + void set_bottom(double bottom) { bottom_ = bottom; } + double get_right() const { return right_; } + void set_right(double right) { right_ = right; } + double get_header() const { return header_; } + void set_header(double header) { header_ = header; } + double get_footer() const { return footer_; } + void set_footer(double footer) { footer_ = footer; } + +private: + double top_; + double left_; + double bottom_; + double right_; + double header_; + double footer_; +}; class worksheet { public: + worksheet(); worksheet(workbook &parent); worksheet(worksheet_struct *root); @@ -993,6 +1033,11 @@ public: bool operator!=(std::nullptr_t) const; std::vector get_relationships(); page_setup &get_page_setup(); + margins &get_page_margins(); + std::string get_auto_filter() const; + void set_auto_filter(const std::string &range_string); + void unset_auto_filter(); + bool has_auto_filter() const; private: friend class workbook; @@ -1006,7 +1051,9 @@ public: named_range() : parent_worksheet_(nullptr), range_string_("") {} named_range(worksheet ws, const std::string &range_string) : parent_worksheet_(ws), range_string_(range_string) {} std::string get_range_string() const { return range_string_; } - worksheet get_parent_worksheet() { return parent_worksheet_; } + worksheet get_scope() const { return parent_worksheet_; } + void set_scope(worksheet scope) { parent_worksheet_ = scope; } + bool operator==(const named_range &comparand) const; private: worksheet parent_worksheet_; @@ -1080,7 +1127,7 @@ public: //named ranges void create_named_range(const std::string &name, worksheet worksheet, const std::string &range_string); std::vector get_named_ranges(); - void add_named_range(named_range named_range); + void add_named_range(const std::string &name, named_range named_range); bool has_named_range(const std::string &name, worksheet ws) const; named_range get_named_range(const std::string &name, worksheet ws); void remove_named_range(named_range named_range);