diff --git a/source/tests/DumpTestSuite.h b/source/tests/DumpTestSuite.h index 90fb42df..fb41eba1 100644 --- a/source/tests/DumpTestSuite.h +++ b/source/tests/DumpTestSuite.h @@ -19,7 +19,7 @@ public: void test_dump_sheet_title() { xlnt::workbook wb3; - wb3.load("C:/Users/taf656/Desktop/a.xlsx"); + wb3.load("/Users/thomas/Desktop/a.xlsx"); xlnt::workbook wb(xlnt::optimized::write); auto ws = wb.create_sheet("Test1"); @@ -102,7 +102,7 @@ public: { xlnt::string_table_builder sb; - std::unordered_map result = {{"a", 0}, {"b", 1}, {"c", 2}, {"d", 3}}; + std::vector> result = {{"a", 0}, {"b", 1}, {"c", 2}, {"d", 3}}; for(auto pair : result) { diff --git a/source/tests/WorksheetTestSuite.h b/source/tests/WorksheetTestSuite.h index 43153001..3c5c7dc0 100644 --- a/source/tests/WorksheetTestSuite.h +++ b/source/tests/WorksheetTestSuite.h @@ -109,7 +109,7 @@ public: void test_cell_alternate_coordinates() { xlnt::worksheet ws(wb); - auto cell = ws.cell(8, 4); + auto cell = ws.cell(4, 8); TS_ASSERT_EQUALS("E9", cell.get_coordinate()); } @@ -215,7 +215,7 @@ public: TS_ASSERT_EQUALS(vals[0][0], "This is A1"); TS_ASSERT_EQUALS(vals[0][1], "This is B1"); TS_ASSERT_EQUALS(vals[1][0], "This is A2"); - TS_ASSERT_EQUALS(vals[1][1], "This is A2"); + TS_ASSERT_EQUALS(vals[1][1], "This is B2"); } void test_rows() diff --git a/source/tests/runner-autogen.cpp b/source/tests/runner-autogen.cpp index 0502444b..fa175fc7 100644 --- a/source/tests/runner-autogen.cpp +++ b/source/tests/runner-autogen.cpp @@ -21,7 +21,7 @@ int main( int argc, char *argv[] ) { return status; } bool suite_CellTestSuite_init = false; -#include "C:\Users\taf656\Development\xlnt\source\tests\CellTestSuite.h" +#include "/Users/thomas/Development/xlnt/source/tests/CellTestSuite.h" static CellTestSuite suite_CellTestSuite; @@ -184,7 +184,7 @@ public: void runTest() { suite_CellTestSuite.test_is_not_date_color_format(); } } testDescription_suite_CellTestSuite_test_is_not_date_color_format; -#include "C:\Users\taf656\Development\xlnt\source\tests\ChartTestSuite.h" +#include "/Users/thomas/Development/xlnt/source/tests/ChartTestSuite.h" static ChartTestSuite suite_ChartTestSuite; @@ -275,7 +275,7 @@ public: void runTest() { suite_ChartTestSuite.test_write_chart_scatter(); } } testDescription_suite_ChartTestSuite_test_write_chart_scatter; -#include "C:\Users\taf656\Development\xlnt\source\tests\DumpTestSuite.h" +#include "/Users/thomas/Development/xlnt/source/tests/DumpTestSuite.h" static DumpTestSuite suite_DumpTestSuite; @@ -318,7 +318,7 @@ public: void runTest() { suite_DumpTestSuite.test_append_after_save(); } } testDescription_suite_DumpTestSuite_test_append_after_save; -#include "C:\Users\taf656\Development\xlnt\source\tests\IterTestSuite.h" +#include "/Users/thomas/Development/xlnt/source/tests/IterTestSuite.h" static IterTestSuite suite_IterTestSuite; @@ -367,7 +367,7 @@ public: void runTest() { suite_IterTestSuite.test_read_single_cell_date(); } } testDescription_suite_IterTestSuite_test_read_single_cell_date; -#include "C:\Users\taf656\Development\xlnt\source\tests\NamedRangeTestSuite.h" +#include "/Users/thomas/Development/xlnt/source/tests/NamedRangeTestSuite.h" static NamedRangeTestSuite suite_NamedRangeTestSuite; @@ -458,7 +458,7 @@ public: void runTest() { suite_NamedRangeTestSuite.test_can_be_saved(); } } testDescription_suite_NamedRangeTestSuite_test_can_be_saved; -#include "C:\Users\taf656\Development\xlnt\source\tests\NullableTestSuite.h" +#include "/Users/thomas/Development/xlnt/source/tests/NullableTestSuite.h" static NullableTestSuite suite_NullableTestSuite; @@ -495,7 +495,7 @@ public: void runTest() { suite_NullableTestSuite.test_copy_constructor(); } } testDescription_suite_NullableTestSuite_test_copy_constructor; -#include "C:\Users\taf656\Development\xlnt\source\tests\NumberFormatTestSuite.h" +#include "/Users/thomas/Development/xlnt/source/tests/NumberFormatTestSuite.h" static NumberFormatTestSuite suite_NumberFormatTestSuite; @@ -598,7 +598,7 @@ public: void runTest() { suite_NumberFormatTestSuite.test_mac_date(); } } testDescription_suite_NumberFormatTestSuite_test_mac_date; -#include "C:\Users\taf656\Development\xlnt\source\tests\PasswordHashTestSuite.h" +#include "/Users/thomas/Development/xlnt/source/tests/PasswordHashTestSuite.h" static PasswordHashTestSuite suite_PasswordHashTestSuite; @@ -617,7 +617,7 @@ public: void runTest() { suite_PasswordHashTestSuite.test_sheet_protection(); } } testDescription_suite_PasswordHashTestSuite_test_sheet_protection; -#include "C:\Users\taf656\Development\xlnt\source\tests\PropsTestSuite.h" +#include "/Users/thomas/Development/xlnt/source/tests/PropsTestSuite.h" static PropsTestSuite suite_PropsTestSuite; @@ -666,7 +666,7 @@ public: void runTest() { suite_PropsTestSuite.test_write_properties_app(); } } testDescription_suite_PropsTestSuite_test_write_properties_app; -#include "C:\Users\taf656\Development\xlnt\source\tests\ReadTestSuite.h" +#include "/Users/thomas/Development/xlnt/source/tests/ReadTestSuite.h" static ReadTestSuite suite_ReadTestSuite; @@ -799,7 +799,7 @@ public: void runTest() { suite_ReadTestSuite.test_read_date_value(); } } testDescription_suite_ReadTestSuite_test_read_date_value; -#include "C:\Users\taf656\Development\xlnt\source\tests\StringsTestSuite.h" +#include "/Users/thomas/Development/xlnt/source/tests/StringsTestSuite.h" static StringsTestSuite suite_StringsTestSuite; @@ -830,7 +830,7 @@ public: void runTest() { suite_StringsTestSuite.test_formatted_string_table(); } } testDescription_suite_StringsTestSuite_test_formatted_string_table; -#include "C:\Users\taf656\Development\xlnt\source\tests\StyleTestSuite.h" +#include "/Users/thomas/Development/xlnt/source/tests/StyleTestSuite.h" static StyleTestSuite suite_StyleTestSuite; @@ -927,7 +927,7 @@ public: void runTest() { suite_StyleTestSuite.test_read_cell_style(); } } testDescription_suite_StyleTestSuite_test_read_cell_style; -#include "C:\Users\taf656\Development\xlnt\source\tests\ThemeTestSuite.h" +#include "/Users/thomas/Development/xlnt/source/tests/ThemeTestSuite.h" static ThemeTestSuite suite_ThemeTestSuite; @@ -940,7 +940,7 @@ public: void runTest() { suite_ThemeTestSuite.test_write_theme(); } } testDescription_suite_ThemeTestSuite_test_write_theme; -#include "C:\Users\taf656\Development\xlnt\source\tests\UnicodeTestSuite.h" +#include "/Users/thomas/Development/xlnt/source/tests/UnicodeTestSuite.h" static UnicodeTestSuite suite_UnicodeTestSuite; @@ -953,7 +953,7 @@ public: void runTest() { suite_UnicodeTestSuite.test_read_workbook_with_unicode_character(); } } testDescription_suite_UnicodeTestSuite_test_read_workbook_with_unicode_character; -#include "C:\Users\taf656\Development\xlnt\source\tests\WorkbookTestSuite.h" +#include "/Users/thomas/Development/xlnt/source/tests/WorkbookTestSuite.h" static WorkbookTestSuite suite_WorkbookTestSuite; @@ -1182,7 +1182,7 @@ public: void runTest() { suite_WorkbookTestSuite.test_good_encoding(); } } testDescription_suite_WorkbookTestSuite_test_good_encoding; -#include "C:\Users\taf656\Development\xlnt\source\tests\WorksheetTestSuite.h" +#include "/Users/thomas/Development/xlnt/source/tests/WorksheetTestSuite.h" static WorksheetTestSuite suite_WorksheetTestSuite; @@ -1357,7 +1357,7 @@ public: void runTest() { suite_WorksheetTestSuite.test_printer_settings(); } } testDescription_suite_WorksheetTestSuite_test_printer_settings; -#include "C:\Users\taf656\Development\xlnt\source\tests\WriteTestSuite.h" +#include "/Users/thomas/Development/xlnt/source/tests/WriteTestSuite.h" static WriteTestSuite suite_WriteTestSuite; @@ -1490,7 +1490,7 @@ public: void runTest() { suite_WriteTestSuite.test_short_number(); } } testDescription_suite_WriteTestSuite_test_short_number; -#include "C:\Users\taf656\Development\xlnt\source\tests\ZipFileTestSuite.h" +#include "/Users/thomas/Development/xlnt/source/tests/ZipFileTestSuite.h" static ZipFileTestSuite suite_ZipFileTestSuite; diff --git a/source/xlnt.cpp b/source/xlnt.cpp index 6af0a6c2..04ae85cd 100644 --- a/source/xlnt.cpp +++ b/source/xlnt.cpp @@ -746,8 +746,7 @@ coordinate cell::coordinate_from_string(const std::string &coord_string) } else { - std::string msg = "Invalid cell coordinates (" + coord_string + ")"; - throw std::runtime_error(msg); + throw bad_cell_coordinates(coord_string); } } else @@ -758,8 +757,7 @@ coordinate cell::coordinate_from_string(const std::string &coord_string) } else if(!(std::isdigit(character, std::locale::classic()) || character == '$')) { - std::string msg = "Invalid cell coordinates (" + coord_string + ")"; - throw std::runtime_error(msg); + throw bad_cell_coordinates(coord_string); } } } @@ -773,8 +771,7 @@ coordinate cell::coordinate_from_string(const std::string &coord_string) if(result.row < 1) { - std::string msg = "Invalid cell coordinates (" + coord_string + ")"; - throw std::runtime_error(msg); + throw bad_cell_coordinates(result.row, cell::column_index_from_string(result.column)); } return result; @@ -925,9 +922,9 @@ xlnt::cell::type cell::get_data_type() const return root_->type; } -xlnt::cell cell::get_offset(int column_offset, int row_offset) +xlnt::cell cell::get_offset(int row_offset, int column_offset) { - return worksheet(root_->parent_worksheet).cell(root_->row + row_offset, root_->column + column_offset); + return worksheet(root_->parent_worksheet).cell(root_->column + column_offset, root_->row + row_offset); } cell &cell::operator=(const cell &rhs) @@ -1061,7 +1058,14 @@ struct worksheet_struct void set_freeze_panes(cell top_left_cell) { - freeze_panes_ = top_left_cell; + if(top_left_cell.get_address() == "A1") + { + unfreeze_panes(); + } + else + { + freeze_panes_ = top_left_cell; + } } void set_freeze_panes(const std::string &top_left_coordinate) @@ -1086,7 +1090,7 @@ struct worksheet_struct return cell_map_[coordinate]; } - xlnt::cell cell(int row, int column) + xlnt::cell cell(int column, int row) { return cell(xlnt::cell::get_column_letter(column + 1) + std::to_string(row + 1)); } @@ -1122,6 +1126,11 @@ struct worksheet_struct xlnt::range range(const std::string &range_string, int row_offset, int column_offset) { xlnt::range r; + + if(parent_.has_named_range(range_string, worksheet(this))) + { + return range(parent_.get_named_range(range_string, worksheet(this)).get_range_string(), row_offset, column_offset); + } auto colon_index = range_string.find(':'); @@ -1137,6 +1146,12 @@ struct worksheet_struct min_coord.column = xlnt::cell::get_column_letter(xlnt::cell::column_index_from_string(min_coord.column) + column_offset); max_coord.column = xlnt::cell::get_column_letter(xlnt::cell::column_index_from_string(max_coord.column) + column_offset); } + + if(row_offset != 0) + { + min_coord.row = min_coord.row + row_offset; + max_coord.row = max_coord.row + row_offset; + } std::unordered_map column_cache; @@ -1145,11 +1160,11 @@ struct worksheet_struct { column_cache[i] = xlnt::cell::get_column_letter(i); } - for(int row = min_coord.row + row_offset; row <= max_coord.row + row_offset; row++) + for(int row = min_coord.row; row <= max_coord.row; row++) { r.push_back(std::vector()); - for(int column = xlnt::cell::column_index_from_string(min_coord.column) + column_offset; - column <= xlnt::cell::column_index_from_string(max_coord.column) + column_offset; column++) + for(int column = xlnt::cell::column_index_from_string(min_coord.column); + column <= xlnt::cell::column_index_from_string(max_coord.column); column++) { std::string coordinate = column_cache[column] + std::to_string(row); r.back().push_back(cell(coordinate)); @@ -1224,33 +1239,41 @@ struct worksheet_struct void append(const std::vector &cells) { int row = get_highest_row(); - if(!cell_map_.empty()) + if(cell_map_.size() != 0) { - row += 1; + row++; } int column = 0; for(auto cell : cells) { - this->cell(row, column++) = cell; + this->cell(column++, row) = cell; } } void append(const std::unordered_map &cells) { int row = get_highest_row(); + if(cell_map_.size() != 0) + { + row++; + } for(auto cell : cells) { - int column = xlnt::cell::column_index_from_string(cell.second); - this->cell(row, column) = cell.second; + int column = xlnt::cell::column_index_from_string(cell.first) - 1; + this->cell(column, row) = cell.second; } } void append(const std::unordered_map &cells) { int row = get_highest_row(); + if(cell_map_.size() != 0) + { + row++; + } for(auto cell : cells) { - this->cell(row, cell.first) = cell.second; + this->cell(cell.first, row) = cell.second; } } @@ -1781,6 +1804,18 @@ worksheet workbook::get_active_sheet() { return worksheets_[active_sheet_index_]; } + +bool workbook::has_named_range(const std::string &name, xlnt::worksheet ws) const +{ + for(auto named_range : named_ranges_) + { + if(named_range.first == name && named_range.second.get_parent_worksheet() == ws) + { + return true; + } + } + return false; +} worksheet workbook::create_sheet() { @@ -1795,9 +1830,30 @@ worksheet workbook::create_sheet() return get_sheet_by_name(title); } -void workbook::create_named_range(const std::string &/*range_string*/, worksheet /*ws*/, const std::string &/*name*/) +void workbook::create_named_range(const std::string &name, worksheet range_owner, const std::string &range_string) { - + for(auto ws : worksheets_) + { + if(ws == range_owner) + { + named_ranges_[name] = named_range(range_owner, range_string); + return; + } + } + + throw std::runtime_error("worksheet isn't owned by this workbook"); +} + +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) + { + return named_range.second; + } + } + throw std::runtime_error("doesn't exist"); } void workbook::load(const std::string &filename) @@ -2075,14 +2131,28 @@ std::string sheet_protection::hash_password(const std::string &plaintext_passwor return hashed; } -int string_table::operator[](const std::string &/*key*/) const +int string_table::operator[](const std::string &key) const { - return 0; + for(std::size_t i = 0; i < strings_.size(); i++) + { + if(key == strings_[i]) + { + return (int)i; + } + } + throw std::runtime_error("bad string"); } -void string_table_builder::add(const std::string &/*string*/) +void string_table_builder::add(const std::string &string) { - + for(std::size_t i = 0; i < table_.strings_.size(); i++) + { + if(string == table_.strings_[i]) + { + return; + } + } + table_.strings_.push_back(string); } } diff --git a/source/xlnt.h b/source/xlnt.h index 9deea297..7efa61b7 100644 --- a/source/xlnt.h +++ b/source/xlnt.h @@ -177,6 +177,12 @@ public: { } + + bad_cell_coordinates(const std::string &coord_string) + : std::runtime_error(std::string("bad cell coordinates: (") + coord_string + ")") + { + + } }; class zip_file @@ -481,6 +487,9 @@ class string_table { public: int operator[](const std::string &key) const; +private: + friend class string_table_builder; + std::vector strings_; }; class string_table_builder @@ -944,6 +953,7 @@ class worksheet { public: worksheet(workbook &parent); + worksheet(worksheet_struct *root); void operator=(const worksheet &other); xlnt::cell operator[](const std::string &address); @@ -985,19 +995,20 @@ public: private: friend class workbook; friend class cell; - worksheet(worksheet_struct *root); worksheet_struct *root_; }; class named_range { public: - named_range(const std::string &name); + 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_; } private: - friend class worksheet; - named_range(named_range_struct *root); - named_range_struct *root_; + worksheet parent_worksheet_; + std::string range_string_; }; class drawing @@ -1068,7 +1079,8 @@ public: 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 get_named_range(const std::string &name); + 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); //serialization @@ -1088,7 +1100,7 @@ private: int active_sheet_index_; encoding_type encoding_; std::vector worksheets_; - std::vector named_ranges_; + std::unordered_map named_ranges_; std::vector relationships_; std::vector drawings_; };