xlnt/source/worksheet/worksheet.cpp

1067 lines
25 KiB
C++
Raw Normal View History

2015-12-25 06:10:02 +08:00
// Copyright (c) 2014-2016 Thomas Fussell
// Copyright (c) 2010-2015 openpyxl
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE
//
// @license: http://www.opensource.org/licenses/mit-license.php
// @author: see AUTHORS file
2014-05-22 05:48:51 +08:00
#include <algorithm>
2016-06-11 22:17:58 +08:00
#include <cmath>
2015-11-02 14:07:43 +08:00
#include <limits>
2014-05-22 05:48:51 +08:00
2014-08-14 06:56:34 +08:00
#include <xlnt/cell/cell.hpp>
2015-11-02 14:07:43 +08:00
#include <xlnt/cell/cell_reference.hpp>
#include <xlnt/cell/index_types.hpp>
#include <xlnt/packaging/relationship.hpp>
#include <xlnt/utils/date.hpp>
#include <xlnt/utils/datetime.hpp>
#include <xlnt/utils/exceptions.hpp>
2015-10-15 06:05:13 +08:00
#include <xlnt/workbook/named_range.hpp>
2014-08-14 06:56:34 +08:00
#include <xlnt/workbook/workbook.hpp>
2016-08-02 06:33:43 +08:00
#include <xlnt/workbook/worksheet_iterator.hpp>
2016-01-25 00:15:49 +08:00
#include <xlnt/worksheet/cell_iterator.hpp>
#include <xlnt/worksheet/const_cell_iterator.hpp>
#include <xlnt/worksheet/const_range_iterator.hpp>
2015-10-15 06:05:13 +08:00
#include <xlnt/worksheet/range.hpp>
2016-01-25 00:15:49 +08:00
#include <xlnt/worksheet/range_iterator.hpp>
2015-10-15 06:05:13 +08:00
#include <xlnt/worksheet/range_reference.hpp>
#include <xlnt/worksheet/worksheet.hpp>
2014-08-14 06:56:34 +08:00
2015-11-02 14:07:43 +08:00
#include <detail/cell_impl.hpp>
#include <detail/constants.hpp>
2016-06-11 01:40:50 +08:00
#include <detail/workbook_impl.hpp>
2015-11-02 14:07:43 +08:00
#include <detail/worksheet_impl.hpp>
2014-05-21 22:20:30 +08:00
namespace xlnt {
2014-05-22 05:48:51 +08:00
worksheet::worksheet() : d_(nullptr)
{
}
2014-05-31 06:42:25 +08:00
worksheet::worksheet(detail::worksheet_impl *d) : d_(d)
2014-05-21 22:20:30 +08:00
{
}
worksheet::worksheet(const worksheet &rhs) : d_(rhs.d_)
2014-05-21 22:20:30 +08:00
{
}
2014-05-21 22:20:30 +08:00
bool worksheet::has_frozen_panes() const
{
return get_frozen_panes() != cell_reference("A1");
2014-05-21 22:20:30 +08:00
}
std::string worksheet::unique_sheet_name(const std::string &value) const
2014-08-02 04:46:54 +08:00
{
2016-08-02 06:33:43 +08:00
auto names = get_workbook().get_sheet_titles();
2014-08-02 04:46:54 +08:00
auto match = std::find(names.begin(), names.end(), value);
2016-08-02 06:33:43 +08:00
2014-08-02 04:46:54 +08:00
std::size_t append = 0;
2016-08-02 06:33:43 +08:00
while (match != names.end())
2014-08-02 04:46:54 +08:00
{
append++;
match = std::find(names.begin(), names.end(), value + std::to_string(append));
2014-08-02 04:46:54 +08:00
}
2016-08-02 06:33:43 +08:00
return append == 0 ? value : value + std::to_string(append);
2014-08-02 04:46:54 +08:00
}
2015-11-11 08:47:31 +08:00
void worksheet::create_named_range(const std::string &name, const std::string &reference_string)
{
create_named_range(name, range_reference(reference_string));
}
void worksheet::create_named_range(const std::string &name, const range_reference &reference)
2014-05-21 22:20:30 +08:00
{
try
{
auto temp = cell_reference::split_reference(name);
2016-07-30 05:50:33 +08:00
// name is a valid reference, make sure it's outside the allowed range
if (column_t(temp.first).index <= column_t("XFD").index && temp.second <= 1048576)
{
throw invalid_parameter(); //("named range name must be outside the range A1-XFD1048576");
}
}
catch (xlnt::invalid_cell_reference)
{
// name is not a valid reference, that's good
}
std::vector<named_range::target> targets;
targets.push_back({ *this, reference });
2016-07-30 05:50:33 +08:00
2015-10-15 06:05:13 +08:00
d_->named_ranges_[name] = named_range(name, targets);
2014-05-21 22:20:30 +08:00
}
range worksheet::operator()(const xlnt::cell_reference &top_left, const xlnt::cell_reference &bottom_right)
{
2015-11-11 08:47:31 +08:00
return get_range(range_reference(top_left, bottom_right));
}
2014-05-22 05:48:51 +08:00
cell worksheet::operator[](const cell_reference &ref)
{
return get_cell(ref);
}
2014-05-21 22:20:30 +08:00
std::vector<range_reference> worksheet::get_merged_ranges() const
{
return d_->merged_cells_;
2014-05-21 22:20:30 +08:00
}
bool worksheet::has_page_margins() const
2015-10-31 06:54:04 +08:00
{
return d_->has_page_margins_;
}
bool worksheet::has_page_setup() const
{
return d_->has_page_setup_;
2015-10-31 06:54:04 +08:00
}
page_margins worksheet::get_page_margins() const
2014-05-21 22:20:30 +08:00
{
return d_->page_margins_;
2014-05-21 22:20:30 +08:00
}
void worksheet::set_page_margins(const page_margins &margins)
{
d_->page_margins_ = margins;
d_->has_page_margins_ = true;
}
2015-11-11 08:47:31 +08:00
void worksheet::auto_filter(const std::string &reference_string)
{
auto_filter(range_reference(reference_string));
}
2014-06-05 06:42:17 +08:00
void worksheet::auto_filter(const range_reference &reference)
2014-05-21 22:20:30 +08:00
{
d_->auto_filter_ = reference;
2014-05-21 22:20:30 +08:00
}
2014-06-05 06:42:17 +08:00
void worksheet::auto_filter(const xlnt::range &range)
2014-05-21 22:20:30 +08:00
{
2014-06-05 06:42:17 +08:00
auto_filter(range.get_reference());
2014-05-21 22:20:30 +08:00
}
range_reference worksheet::get_auto_filter() const
{
return d_->auto_filter_;
2014-05-21 22:20:30 +08:00
}
bool worksheet::has_auto_filter() const
{
return d_->auto_filter_.get_width() > 0;
2014-05-21 22:20:30 +08:00
}
void worksheet::unset_auto_filter()
{
2015-10-15 06:05:13 +08:00
d_->auto_filter_ = range_reference(1, 1, 1, 1);
2014-05-21 22:20:30 +08:00
}
void worksheet::set_page_setup(const page_setup &setup)
2015-10-31 06:54:04 +08:00
{
d_->has_page_setup_ = true;
d_->page_setup_ = setup;
2015-10-31 06:54:04 +08:00
}
page_setup worksheet::get_page_setup() const
2014-05-21 22:20:30 +08:00
{
if (!d_->has_page_setup_)
{
throw invalid_attribute();
}
return d_->page_setup_;
2014-05-21 22:20:30 +08:00
}
std::string worksheet::to_string() const
2014-05-21 22:20:30 +08:00
{
return "<Worksheet \"" + d_->title_ + "\">";
2014-05-21 22:20:30 +08:00
}
2016-05-12 07:24:53 +08:00
workbook &worksheet::get_workbook()
2014-05-21 22:20:30 +08:00
{
return *d_->parent_;
2014-05-21 22:20:30 +08:00
}
2016-05-12 07:24:53 +08:00
const workbook &worksheet::get_workbook() const
{
return *d_->parent_;
}
2014-05-21 22:20:30 +08:00
void worksheet::garbage_collect()
{
auto cell_map_iter = d_->cell_map_.begin();
2014-07-25 05:31:46 +08:00
while (cell_map_iter != d_->cell_map_.end())
{
auto cell_iter = cell_map_iter->second.begin();
2014-07-25 05:31:46 +08:00
while (cell_iter != cell_map_iter->second.end())
{
2014-07-25 05:31:46 +08:00
cell current_cell(&cell_iter->second);
if (current_cell.garbage_collectible())
{
cell_iter = cell_map_iter->second.erase(cell_iter);
continue;
}
2014-07-25 05:31:46 +08:00
cell_iter++;
}
2014-07-25 05:31:46 +08:00
if (cell_map_iter->second.empty())
{
cell_map_iter = d_->cell_map_.erase(cell_map_iter);
continue;
}
2014-07-25 05:31:46 +08:00
cell_map_iter++;
}
2014-05-21 22:20:30 +08:00
}
void worksheet::set_id(std::size_t id)
{
d_->id_ = id;
}
std::size_t worksheet::get_id() const
{
return d_->id_;
}
std::string worksheet::get_title() const
2014-05-21 22:20:30 +08:00
{
return d_->title_;
2014-05-21 22:20:30 +08:00
}
void worksheet::set_title(const std::string &title)
2014-05-21 22:20:30 +08:00
{
2016-08-02 06:33:43 +08:00
if (title.length() > 31)
{
throw invalid_sheet_title(title);
}
if (title.find_first_of("*:/\\?[]") != std::string::npos)
{
throw invalid_sheet_title(title);
}
auto same_title = std::find_if(get_workbook().begin(), get_workbook().end(),
[&](worksheet ws) { return ws.get_title() == title; });
if (same_title != get_workbook().end() && *same_title != *this)
{
throw invalid_sheet_title(title);
}
2016-10-10 19:01:19 +08:00
get_workbook().d_->sheet_title_rel_id_map_[title] =
get_workbook().d_->sheet_title_rel_id_map_[d_->title_];
get_workbook().d_->sheet_title_rel_id_map_.erase(d_->title_);
2016-08-02 06:33:43 +08:00
d_->title_ = title;
2014-05-21 22:20:30 +08:00
}
cell_reference worksheet::get_frozen_panes() const
{
return d_->view_.get_pane().top_left_cell;
2014-05-21 22:20:30 +08:00
}
void worksheet::freeze_panes(xlnt::cell top_left_cell)
{
freeze_panes(top_left_cell.get_reference().to_string());
2014-05-21 22:20:30 +08:00
}
void worksheet::freeze_panes(const std::string &top_left_coordinate)
2014-05-21 22:20:30 +08:00
{
auto ref = cell_reference(top_left_coordinate);
d_->view_.get_pane().top_left_cell = ref;
d_->view_.get_pane().state = pane_state::frozen;
d_->view_.get_selections().clear();
d_->view_.get_selections().push_back(selection());
if (ref.get_column_index() == 1
&& ref.get_row() == 1)
{
d_->view_.get_selections().back().set_pane(pane_corner::top_left);
d_->view_.get_pane().active_pane = pane_corner::top_left;
d_->view_.get_pane().state = pane_state::normal;
}
else if (ref.get_column_index() == 1)
{
d_->view_.get_selections().back().set_pane(pane_corner::bottom_left);
d_->view_.get_pane().active_pane = pane_corner::bottom_left;
d_->view_.get_pane().y_split = ref.get_row() - 1;
}
else if (ref.get_row() == 1)
{
d_->view_.get_selections().back().set_pane(pane_corner::top_right);
d_->view_.get_pane().active_pane = pane_corner::top_right;
d_->view_.get_pane().x_split = ref.get_column_index().index - 1;
}
else
{
d_->view_.get_selections().push_back(selection());
d_->view_.get_selections().push_back(selection());
d_->view_.get_selections()[0].set_pane(pane_corner::top_right);
d_->view_.get_selections()[1].set_pane(pane_corner::bottom_left);
d_->view_.get_selections()[2].set_pane(pane_corner::bottom_right);
d_->view_.get_pane().active_pane = pane_corner::bottom_right;
d_->view_.get_pane().x_split = ref.get_column_index().index - 1;
d_->view_.get_pane().y_split = ref.get_row() - 1;
}
2014-05-21 22:20:30 +08:00
}
void worksheet::unfreeze_panes()
{
d_->view_.get_pane().top_left_cell = cell_reference("A1");
d_->view_.get_pane().state = pane_state::normal;
2014-05-21 22:20:30 +08:00
}
cell worksheet::get_cell(const cell_reference &reference)
{
if (d_->cell_map_.find(reference.get_row()) == d_->cell_map_.end())
{
d_->cell_map_[reference.get_row()] = std::unordered_map<column_t, detail::cell_impl>();
}
auto &row = d_->cell_map_[reference.get_row()];
if (row.find(reference.get_column_index()) == row.end())
{
2016-08-18 19:34:18 +08:00
auto &impl = row[reference.get_column_index()] = detail::cell_impl();
impl.parent_ = d_;
impl.column_ = reference.get_column_index();
impl.row_ = reference.get_row();
}
return cell(&row[reference.get_column_index()]);
2014-05-21 22:20:30 +08:00
}
2014-05-22 05:48:51 +08:00
const cell worksheet::get_cell(const cell_reference &reference) const
{
return cell(&d_->cell_map_.at(reference.get_row()).at(reference.get_column_index()));
2014-05-22 05:48:51 +08:00
}
bool worksheet::has_cell(const cell_reference &reference) const
{
const auto row = d_->cell_map_.find(reference.get_row());
if(row == d_->cell_map_.cend())
return false;
const auto col = row->second.find(reference.get_column_index());
if(col == row->second.cend())
return false;
return true;
}
2014-06-11 05:12:15 +08:00
bool worksheet::has_row_properties(row_t row) const
{
return d_->row_properties_.find(row) != d_->row_properties_.end();
}
range worksheet::get_named_range(const std::string &name)
2014-05-21 22:20:30 +08:00
{
2016-05-12 07:24:53 +08:00
if (!get_workbook().has_named_range(name))
{
2016-07-30 06:55:49 +08:00
throw key_not_found();
}
if (!has_named_range(name))
{
2016-07-30 06:55:49 +08:00
throw key_not_found();
}
2015-10-15 06:05:13 +08:00
return get_range(d_->named_ranges_[name].get_targets()[0].second);
}
column_t worksheet::get_lowest_column() const
{
if (d_->cell_map_.empty())
{
2016-07-23 08:26:02 +08:00
return constants::min_column();
}
2016-07-23 08:26:02 +08:00
column_t lowest = constants::max_column();
for (auto &row : d_->cell_map_)
{
for (auto &c : row.second)
{
lowest = std::min(lowest, c.first);
}
}
return lowest;
}
row_t worksheet::get_lowest_row() const
{
if (d_->cell_map_.empty())
{
2016-07-23 08:26:02 +08:00
return constants::min_row();
}
2016-07-23 08:26:02 +08:00
row_t lowest = constants::max_row();
for (auto &row : d_->cell_map_)
{
lowest = std::min(lowest, row.first);
}
return lowest;
2014-05-21 22:20:30 +08:00
}
row_t worksheet::get_highest_row() const
2014-05-21 22:20:30 +08:00
{
2016-07-23 08:26:02 +08:00
row_t highest = constants::min_row();
for (auto &row : d_->cell_map_)
{
highest = std::max(highest, row.first);
}
return highest;
2014-05-21 22:20:30 +08:00
}
column_t worksheet::get_highest_column() const
2014-05-21 22:20:30 +08:00
{
2016-07-23 08:26:02 +08:00
column_t highest = constants::min_column();
for (auto &row : d_->cell_map_)
{
for (auto &c : row.second)
{
highest = std::max(highest, c.first);
}
}
return highest;
2014-05-21 22:20:30 +08:00
}
bool worksheet::has_dimension() const
{
return d_->has_dimension_;
}
bool worksheet::has_format_properties() const
{
return d_->has_format_properties_;
}
2014-05-21 22:20:30 +08:00
range_reference worksheet::calculate_dimension() const
{
2015-10-15 06:05:13 +08:00
auto lowest_column = get_lowest_column();
auto lowest_row = get_lowest_row();
2015-10-15 06:05:13 +08:00
auto highest_column = get_highest_column();
auto highest_row = get_highest_row();
return range_reference(lowest_column, lowest_row, highest_column, highest_row);
2014-05-21 22:20:30 +08:00
}
2015-11-11 08:47:31 +08:00
range worksheet::get_range(const std::string &reference_string)
{
return get_range(range_reference(reference_string));
}
2014-05-21 22:20:30 +08:00
range worksheet::get_range(const range_reference &reference)
{
return range(*this, reference);
}
2015-11-11 08:47:31 +08:00
const range worksheet::get_range(const std::string &reference_string) const
{
return get_range(range_reference(reference_string));
}
const range worksheet::get_range(const range_reference &reference) const
{
return range(*this, reference);
2014-05-21 22:20:30 +08:00
}
2015-11-11 08:47:31 +08:00
void worksheet::merge_cells(const std::string &reference_string)
{
merge_cells(range_reference(reference_string));
}
void worksheet::unmerge_cells(const std::string &reference_string)
{
unmerge_cells(range_reference(reference_string));
}
2014-05-21 22:20:30 +08:00
void worksheet::merge_cells(const range_reference &reference)
{
d_->merged_cells_.push_back(reference);
bool first = true;
for (auto row : get_range(reference))
{
for (auto cell : row)
{
cell.set_merged(true);
2014-07-26 04:39:25 +08:00
if (!first)
{
if (cell.get_data_type() == cell::type::string)
2014-07-26 04:39:25 +08:00
{
cell.set_value("");
2014-07-26 04:39:25 +08:00
}
else
{
cell.clear_value();
2014-07-26 04:39:25 +08:00
}
}
2014-07-26 04:39:25 +08:00
first = false;
}
}
2014-05-21 22:20:30 +08:00
}
void worksheet::merge_cells(column_t start_column, row_t start_row, column_t end_column, row_t end_row)
{
merge_cells(xlnt::range_reference(start_column, start_row, end_column, end_row));
}
2014-05-21 22:20:30 +08:00
void worksheet::unmerge_cells(const range_reference &reference)
{
auto match = std::find(d_->merged_cells_.begin(), d_->merged_cells_.end(), reference);
if (match == d_->merged_cells_.end())
{
throw invalid_parameter();
}
d_->merged_cells_.erase(match);
for (auto row : get_range(reference))
{
for (auto cell : row)
{
cell.set_merged(false);
}
}
2014-05-21 22:20:30 +08:00
}
void worksheet::unmerge_cells(column_t start_column, row_t start_row, column_t end_column, row_t end_row)
{
unmerge_cells(xlnt::range_reference(start_column, start_row, end_column, end_row));
}
2014-05-21 22:20:30 +08:00
void worksheet::append()
{
get_cell(cell_reference(1, get_next_row()));
}
void worksheet::append(const std::vector<std::string> &cells)
2014-05-21 22:20:30 +08:00
{
xlnt::cell_reference next(1, get_next_row());
for (auto cell : cells)
2014-05-31 06:42:25 +08:00
{
get_cell(next).set_value(cell);
next.set_column_index(next.get_column_index() + 1);
2014-05-31 06:42:25 +08:00
}
}
row_t worksheet::get_next_row() const
{
2015-10-15 06:05:13 +08:00
auto row = get_highest_row() + 1;
if (row == 2 && d_->cell_map_.size() == 0)
2014-05-31 06:42:25 +08:00
{
row = 1;
2014-05-31 06:42:25 +08:00
}
return row;
2014-05-31 06:42:25 +08:00
}
void worksheet::append(const std::vector<int> &cells)
{
xlnt::cell_reference next(1, get_next_row());
for (auto cell : cells)
2014-05-31 06:42:25 +08:00
{
get_cell(next).set_value(cell);
next.set_column_index(next.get_column_index() + 1);
2014-05-31 06:42:25 +08:00
}
}
void worksheet::append(const std::unordered_map<std::string, std::string> &cells)
{
auto row = get_next_row();
for (auto cell : cells)
{
get_cell(cell_reference(cell.first, row)).set_value(cell.second);
}
2014-05-21 22:20:30 +08:00
}
void worksheet::append(const std::unordered_map<int, std::string> &cells)
2014-05-21 22:20:30 +08:00
{
auto row = get_next_row();
for (auto cell : cells)
{
2015-10-15 06:05:13 +08:00
get_cell(cell_reference(static_cast<column_t>(cell.first), row)).set_value(cell.second);
}
}
void worksheet::append(const std::vector<int>::const_iterator begin, const std::vector<int>::const_iterator end)
{
xlnt::cell_reference next(1, get_next_row());
for (auto i = begin; i != end; i++)
{
get_cell(next).set_value(*i);
next.set_column_index(next.get_column_index() + 1);
}
2014-05-21 22:20:30 +08:00
}
xlnt::range worksheet::rows() const
{
return get_range(calculate_dimension());
2014-05-21 22:20:30 +08:00
}
xlnt::range worksheet::rows(const std::string &range_string) const
{
return get_range(range_reference(range_string));
}
xlnt::range worksheet::rows(const std::string &range_string, int row_offset, int column_offset) const
{
range_reference reference(range_string);
return get_range(reference.make_offset(column_offset, row_offset));
}
xlnt::range worksheet::rows(int row_offset, int column_offset) const
{
range_reference reference(calculate_dimension());
return get_range(reference.make_offset(column_offset, row_offset));
}
2014-07-20 04:59:05 +08:00
xlnt::range worksheet::columns() const
{
return range(*this, calculate_dimension(), major_order::column);
2014-07-20 04:59:05 +08:00
}
2014-05-21 22:20:30 +08:00
bool worksheet::operator==(const worksheet &other) const
{
2016-03-06 10:39:50 +08:00
return compare(other, true);
}
bool worksheet::compare(const worksheet &other, bool reference) const
{
if(reference)
{
return d_ == other.d_;
}
if(d_->parent_ != other.d_->parent_) return false;
for(auto &row : d_->cell_map_)
{
if(other.d_->cell_map_.find(row.first) == other.d_->cell_map_.end())
{
return false;
}
for(auto &cell : row.second)
{
if(other.d_->cell_map_[row.first].find(cell.first) == other.d_->cell_map_[row.first].end())
{
return false;
}
xlnt::cell this_cell(&cell.second);
xlnt::cell other_cell(&other.d_->cell_map_[row.first][cell.first]);
2016-06-23 16:33:10 +08:00
if (this_cell.get_data_type() != other_cell.get_data_type())
{
return false;
}
if (this_cell.get_data_type() == xlnt::cell::type::numeric && this_cell.get_value<long double>() != other_cell.get_value<long double>())
2016-03-06 10:39:50 +08:00
{
return false;
}
}
}
// todo: missing some comparisons
if(d_->auto_filter_ == other.d_->auto_filter_
&& d_->comment_count_ == other.d_->comment_count_
&& d_->view_.get_pane().top_left_cell == other.d_->view_.get_pane().top_left_cell
2016-03-06 10:39:50 +08:00
&& d_->merged_cells_ == other.d_->merged_cells_
&& d_->relationships_ == other.d_->relationships_)
{
return true;
}
return false;
2014-05-21 22:20:30 +08:00
}
bool worksheet::operator!=(const worksheet &other) const
{
2016-03-06 10:39:50 +08:00
return !(*this == other);
2014-05-21 22:20:30 +08:00
}
bool worksheet::operator==(std::nullptr_t) const
{
return d_ == nullptr;
2014-05-21 22:20:30 +08:00
}
bool worksheet::operator!=(std::nullptr_t) const
{
return d_ != nullptr;
2014-05-21 22:20:30 +08:00
}
void worksheet::operator=(const worksheet &other)
{
d_ = other.d_;
2014-05-21 22:20:30 +08:00
}
2014-05-22 05:48:51 +08:00
const cell worksheet::operator[](const cell_reference &ref) const
2014-05-21 22:20:30 +08:00
{
return get_cell(ref);
}
range worksheet::operator[](const range_reference &ref)
{
return get_range(ref);
}
range worksheet::operator[](const std::string &name)
2014-05-21 22:20:30 +08:00
{
if (has_named_range(name))
2014-05-21 22:20:30 +08:00
{
return get_named_range(name);
}
return get_range(range_reference(name));
}
bool worksheet::has_named_range(const std::string &name)
2014-05-21 22:20:30 +08:00
{
return d_->named_ranges_.find(name) != d_->named_ranges_.end();
2014-05-21 22:20:30 +08:00
}
void worksheet::remove_named_range(const std::string &name)
2014-05-21 22:20:30 +08:00
{
if (!has_named_range(name))
{
throw key_not_found();
}
d_->named_ranges_.erase(name);
2014-05-21 22:20:30 +08:00
}
2014-05-22 05:48:51 +08:00
void worksheet::reserve(std::size_t n)
{
d_->cell_map_.reserve(n);
2014-05-22 05:48:51 +08:00
}
void worksheet::increment_comments()
2014-07-20 02:43:48 +08:00
{
d_->comment_count_++;
2014-07-20 02:43:48 +08:00
}
void worksheet::decrement_comments()
2014-07-20 02:43:48 +08:00
{
d_->comment_count_--;
2014-07-20 02:43:48 +08:00
}
std::size_t worksheet::get_comment_count() const
{
return d_->comment_count_;
2014-07-20 02:43:48 +08:00
}
2014-07-20 04:59:05 +08:00
header_footer &worksheet::get_header_footer()
{
return d_->header_footer_;
}
const header_footer &worksheet::get_header_footer() const
{
return d_->header_footer_;
}
header_footer::header_footer()
{
}
2014-07-24 08:51:28 +08:00
header::header() : default_(true), font_size_(12)
2014-07-20 04:59:05 +08:00
{
}
2014-07-24 08:51:28 +08:00
footer::footer() : default_(true), font_size_(12)
2014-07-20 04:59:05 +08:00
{
}
2014-07-24 08:51:28 +08:00
void worksheet::set_parent(xlnt::workbook &wb)
{
d_->parent_ = &wb;
}
std::vector<std::string> worksheet::get_formula_attributes() const
2014-07-25 05:31:46 +08:00
{
return {};
}
2014-07-26 04:39:25 +08:00
cell_reference worksheet::get_point_pos(int left, int top) const
{
static const double DefaultColumnWidth = 51.85;
static const double DefaultRowHeight = 15.0;
2015-11-03 05:45:05 +08:00
auto points_to_pixels = [](long double value, long double dpi)
{
return static_cast<int>(std::ceil(value * dpi / 72));
};
2014-07-26 04:39:25 +08:00
auto default_height = points_to_pixels(DefaultRowHeight, 96.0);
auto default_width = points_to_pixels(DefaultColumnWidth, 96.0);
column_t current_column = 1;
row_t current_row = 1;
2014-07-26 04:39:25 +08:00
int left_pos = 0;
int top_pos = 0;
while (left_pos <= left)
2014-07-26 04:39:25 +08:00
{
current_column++;
if (has_column_properties(current_column))
2014-07-26 04:39:25 +08:00
{
2015-10-29 03:08:54 +08:00
auto cdw = get_column_properties(current_column).width;
2014-07-26 04:39:25 +08:00
if (cdw >= 0)
2014-07-26 04:39:25 +08:00
{
left_pos += points_to_pixels(cdw, 96.0);
continue;
}
}
left_pos += default_width;
}
while (top_pos <= top)
2014-07-26 04:39:25 +08:00
{
current_row++;
if (has_row_properties(current_row))
2014-07-26 04:39:25 +08:00
{
2015-10-29 03:08:54 +08:00
auto cdh = get_row_properties(current_row).height;
2014-07-26 04:39:25 +08:00
if (cdh >= 0)
2014-07-26 04:39:25 +08:00
{
top_pos += points_to_pixels(cdh, 96.0);
continue;
}
}
top_pos += default_height;
}
return { current_column - 1, current_row - 1 };
2014-07-26 04:39:25 +08:00
}
cell_reference worksheet::get_point_pos(const std::pair<int, int> &point) const
{
return get_point_pos(point.first, point.second);
}
void worksheet::set_sheet_state(sheet_state state)
2015-10-14 12:03:48 +08:00
{
get_page_setup().set_sheet_state(state);
}
2016-07-30 05:50:33 +08:00
sheet_state worksheet::get_sheet_state() const
{
return get_page_setup().get_sheet_state();
}
2014-07-26 04:39:25 +08:00
2015-10-29 03:08:54 +08:00
void worksheet::add_column_properties(column_t column, const xlnt::column_properties &props)
{
d_->column_properties_[column] = props;
}
bool worksheet::has_column_properties(column_t column) const
{
return d_->column_properties_.find(column) != d_->column_properties_.end();
}
column_properties &worksheet::get_column_properties(column_t column)
{
return d_->column_properties_[column];
}
const column_properties &worksheet::get_column_properties(column_t column) const
{
return d_->column_properties_.at(column);
}
row_properties &worksheet::get_row_properties(row_t row)
{
return d_->row_properties_[row];
}
const row_properties &worksheet::get_row_properties(row_t row) const
{
return d_->row_properties_.at(row);
}
worksheet::iterator worksheet::begin()
{
auto dimensions = calculate_dimension();
cell_reference top_right(dimensions.get_bottom_right().get_column_index(), dimensions.get_top_left().get_row());
range_reference row_range(dimensions.get_top_left(), top_right);
return iterator(*this, row_range, major_order::row);
}
worksheet::iterator worksheet::end()
{
auto dimensions = calculate_dimension();
auto past_end_row_index = dimensions.get_bottom_right().get_row() + 1;
cell_reference bottom_left(dimensions.get_top_left().get_column_index(), past_end_row_index);
cell_reference bottom_right(dimensions.get_bottom_right().get_column_index(), past_end_row_index);
return iterator(*this, range_reference(bottom_left, bottom_right), major_order::row);
}
worksheet::const_iterator worksheet::cbegin() const
{
auto dimensions = calculate_dimension();
cell_reference top_right(dimensions.get_bottom_right().get_column_index(), dimensions.get_top_left().get_row());
range_reference row_range(dimensions.get_top_left(), top_right);
return const_iterator(*this, row_range, major_order::row);
}
worksheet::const_iterator worksheet::cend() const
{
auto dimensions = calculate_dimension();
auto past_end_row_index = dimensions.get_bottom_right().get_row() + 1;
cell_reference bottom_left(dimensions.get_top_left().get_column_index(), past_end_row_index);
cell_reference bottom_right(dimensions.get_bottom_right().get_column_index(), past_end_row_index);
return const_iterator(*this, range_reference(bottom_left, bottom_right), major_order::row);
}
worksheet::const_iterator worksheet::begin() const
{
return cbegin();
}
worksheet::const_iterator worksheet::end() const
{
return cend();
}
range worksheet::iter_cells(bool skip_null)
{
return range(*this, calculate_dimension(), major_order::row, skip_null);
}
void worksheet::add_print_title(int i)
{
add_print_title(i, "rows");
}
void worksheet::add_print_title(int i, const std::string &rows_or_cols)
{
if(rows_or_cols == "cols")
{
set_print_title_cols("A:" + column_t::column_string_from_index(i));
}
else
{
set_print_title_rows("1:" + std::to_string(i));
}
}
void worksheet::set_print_title_rows(const std::string &rows)
{
d_->print_title_rows_ = rows;
}
void worksheet::set_print_title_cols(const std::string &cols)
{
d_->print_title_cols_ = cols;
}
std::string worksheet::get_print_titles() const
{
if (!d_->print_title_rows_.empty() && !d_->print_title_cols_.empty())
{
return d_->title_ + "!" + d_->print_title_rows_ + "," + d_->title_ + "!" + d_->print_title_cols_;
}
else if (!d_->print_title_cols_.empty())
{
return d_->title_ + "!" + d_->print_title_cols_;
}
else
{
return d_->title_ + "!" + d_->print_title_rows_;
}
}
void worksheet::set_print_area(const std::string &print_area)
{
d_->print_area_ = range_reference::make_absolute(range_reference(print_area));
}
range_reference worksheet::get_print_area() const
{
return d_->print_area_;
}
bool worksheet::has_view() const
{
return d_->has_view_;
}
sheet_view worksheet::get_view() const
{
return d_->view_;
}
bool worksheet::x14ac_enabled() const
{
return d_->x14ac_;
}
void worksheet::enable_x14ac()
{
d_->x14ac_ = true;
}
void worksheet::disable_x14ac()
{
d_->x14ac_ = false;
}
2014-05-21 22:20:30 +08:00
} // namespace xlnt