#include #include #include #include namespace xlnt { column_t::index_t column_t::column_index_from_string(const string &column_string) { if (column_string.length() > 3 || column_string.empty()) { throw column_string_index_exception(); } column_t::index_t column_index = 0; int place = 1; auto is_alpha = [](string::code_point c) { return (c >= U'A' && c <= U'Z') || (c >= U'a' && c <= U'z'); }; auto column_string_upper = column_string.to_upper(); for (int i = static_cast(column_string.length()) - 1; i >= 0; i--) { auto index = static_cast(i); if (!is_alpha(column_string[index])) { throw column_string_index_exception(); } auto char_index = column_string_upper[index] - U'A'; column_index += static_cast((char_index + 1) * place); place *= 26; } return column_index; } // Convert a column number into a column letter (3 -> 'C') // Right shift the column col_idx by 26 to find column letters in reverse // order.These numbers are 1 - based, and can be converted to ASCII // ordinals by adding 64. string column_t::column_string_from_index(column_t::index_t column_index) { // these indicies corrospond to A->ZZZ and include all allowed // columns if (column_index < constants::MinColumn() || column_index > constants::MaxColumn()) { // auto msg = "Column index out of bounds: " + string::from(column_index); throw column_string_index_exception(); } int temp = static_cast(column_index); string column_letter = ""; while (temp > 0) { int quotient = temp / 26, remainder = temp % 26; // check for exact division and borrow if needed if (remainder == 0) { quotient -= 1; remainder = 26; } string char_string; char_string.append(char(remainder + 64)); column_letter = char_string + column_letter; temp = quotient; } return column_letter; } std::size_t column_hash::operator()(const column_t &k) const { static std::hash hasher; return hasher(k.index); } } // namespace xlnt