#pragma once #include #include #include #include #include #include #include #include #include #include namespace { // return s after checking encoding, size, and illegal characters xlnt::string check_string(xlnt::string s) { if (s.length() == 0) { return s; } // check encoding? if (s.length() > 32767) { s = s.substr(0, 32767); // max string length in Excel } for (auto c : s) { if (c <= 8 || c == 11 || c == 12 || (c >= 14 && c <= 31)) { throw xlnt::illegal_character_error(c); } } return s; } std::pair cast_numeric(const xlnt::string &s) { const char *str = s.data(); char *str_end = nullptr; auto result = std::strtold(str, &str_end); if (str_end != str + s.length()) return { false, 0 }; return { true, result }; } std::pair cast_percentage(const xlnt::string &s) { if (s.back() == '%') { auto number = cast_numeric(s.substr(0, s.length() - 1)); if (number.first) { return { true, number.second / 100 }; } } return { false, 0 }; } std::pair cast_time(const xlnt::string &s) { xlnt::time result; try { auto last_colon = s.find_last_of(':'); if (last_colon == xlnt::string::npos) { return { false, result }; } double seconds = s.substr(last_colon + 1).to(); result.second = static_cast(seconds); result.microsecond = static_cast((seconds - static_cast(result.second)) * 1e6); auto first_colon = s.find(':'); if (first_colon == last_colon) { auto decimal_pos = s.find('.'); if (decimal_pos != xlnt::string::npos) { result.minute = s.substr(0, first_colon).to(); } else { result.hour = s.substr(0, first_colon).to(); result.minute = result.second; result.second = 0; } } else { result.hour = s.substr(0, first_colon).to(); result.minute = s.substr(first_colon + 1, last_colon - first_colon - 1).to(); } } catch (std::invalid_argument) { return { false, result }; } return { true, result }; } } // namespace namespace xlnt { class style; namespace detail { struct worksheet_impl; struct cell_impl { cell_impl(); cell_impl(column_t column, row_t row); cell_impl(worksheet_impl *parent, column_t column, row_t row); cell_impl(const cell_impl &rhs); cell_impl &operator=(const cell_impl &rhs); cell self() { return xlnt::cell(this); } void set_string(const string &s, bool guess_types) { value_string_ = check_string(s); type_ = cell::type::string; if (value_string_.length() > 1 && value_string_.front() == '=') { formula_ = value_string_; type_ = cell::type::formula; value_string_.length(); } else if (cell::error_codes().find(s) != cell::error_codes().end()) { type_ = cell::type::error; } else if (guess_types) { auto percentage = cast_percentage(s); if (percentage.first) { value_numeric_ = percentage.second; type_ = cell::type::numeric; self().set_number_format(xlnt::number_format::percentage()); } else { auto time = cast_time(s); if (time.first) { type_ = cell::type::numeric; self().set_number_format(number_format::date_time6()); value_numeric_ = time.second.to_number(); } else { auto numeric = cast_numeric(s); if (numeric.first) { value_numeric_ = numeric.second; type_ = cell::type::numeric; } } } } } cell::type type_; worksheet_impl *parent_; column_t column_; row_t row_; string value_string_; long double value_numeric_; string formula_; bool has_hyperlink_; relationship hyperlink_; bool is_merged_; bool has_style_; std::size_t style_id_; std::unique_ptr comment_; }; } // namespace detail } // namespace xlnt