From 12007fe2d89228b9b92da3c8fcc996cf7bbc4449 Mon Sep 17 00:00:00 2001 From: Thomas Fussell Date: Fri, 8 Sep 2017 21:05:34 -0400 Subject: [PATCH] change cell numeric value type from long double to double, closes #201 --- include/xlnt/cell/cell.hpp | 8 ---- include/xlnt/styles/number_format.hpp | 2 +- include/xlnt/utils/datetime.hpp | 4 +- include/xlnt/utils/time.hpp | 4 +- include/xlnt/utils/timedelta.hpp | 4 +- source/cell/cell.cpp | 40 +++++++------------ source/detail/implementations/cell_impl.hpp | 2 +- .../detail/number_format/number_formatter.cpp | 16 ++++---- .../detail/number_format/number_formatter.hpp | 14 +++---- source/detail/serialization/xlsx_consumer.cpp | 4 +- source/detail/serialization/xlsx_producer.cpp | 10 ++--- source/styles/number_format.cpp | 2 +- source/utils/datetime.cpp | 16 +++++--- source/utils/time.cpp | 4 +- source/utils/timedelta.cpp | 10 ++--- source/worksheet/worksheet.cpp | 2 +- tests/cell/cell_test_suite.hpp | 23 +++++------ tests/styles/number_format_test_suite.hpp | 6 +-- tests/utils/timedelta_test_suite.hpp | 6 +-- tests/workbook/serialization_test_suite.hpp | 3 -- 20 files changed, 80 insertions(+), 100 deletions(-) diff --git a/include/xlnt/cell/cell.hpp b/include/xlnt/cell/cell.hpp index fa83508a..e65eab09 100644 --- a/include/xlnt/cell/cell.hpp +++ b/include/xlnt/cell/cell.hpp @@ -156,11 +156,6 @@ public: /// void value(double float_value); - /// - /// Sets the value of this cell to the given value. - /// - void value(long double float_value); - /// /// Sets the value of this cell to the given value. /// @@ -671,9 +666,6 @@ float cell::value() const; template<> double cell::value() const; -template<> -long double cell::value() const; - template<> date cell::value() const; diff --git a/include/xlnt/styles/number_format.hpp b/include/xlnt/styles/number_format.hpp index 46869540..8d0574a1 100644 --- a/include/xlnt/styles/number_format.hpp +++ b/include/xlnt/styles/number_format.hpp @@ -242,7 +242,7 @@ public: /// Returns number formatted according to this number format's format code /// with the given base date. /// - std::string format(long double number, calendar base_date) const; + std::string format(double number, calendar base_date) const; /// /// Returns true if this format code returns a number formatted as a date. diff --git a/include/xlnt/utils/datetime.hpp b/include/xlnt/utils/datetime.hpp index e8a42f9e..24ca7656 100644 --- a/include/xlnt/utils/datetime.hpp +++ b/include/xlnt/utils/datetime.hpp @@ -54,7 +54,7 @@ struct XLNT_API datetime /// a date and the fractional part into a time according to date::from_number /// and time::from_number. /// - static datetime from_number(long double number, calendar base_date); + static datetime from_number(double number, calendar base_date); /// /// Returns a datetime equivalent to the ISO-formatted string iso_string. @@ -84,7 +84,7 @@ struct XLNT_API datetime /// /// Returns this datetime as a number of seconds since 1900 or 1904 (depending on base_date provided). /// - long double to_number(calendar base_date) const; + double to_number(calendar base_date) const; /// /// Returns true if this datetime is equivalent to comparand. diff --git a/include/xlnt/utils/time.hpp b/include/xlnt/utils/time.hpp index c275f3fb..36d6f429 100644 --- a/include/xlnt/utils/time.hpp +++ b/include/xlnt/utils/time.hpp @@ -46,7 +46,7 @@ struct XLNT_API time /// The integer part of number will be ignored. /// 0.5 would return time(12, 0, 0, 0) or noon, halfway through the day. /// - static time from_number(long double number); + static time from_number(double number); /// /// Constructs a time object from an optional hour, minute, second, and microsecond. @@ -62,7 +62,7 @@ struct XLNT_API time /// Returns a numeric representation of the time in the range 0-1 where the value /// is equal to the fraction of the day elapsed. /// - long double to_number() const; + double to_number() const; /// /// Returns true if this time is equivalent to comparand. diff --git a/include/xlnt/utils/timedelta.hpp b/include/xlnt/utils/timedelta.hpp index 6ea773b1..797e6d95 100644 --- a/include/xlnt/utils/timedelta.hpp +++ b/include/xlnt/utils/timedelta.hpp @@ -38,7 +38,7 @@ struct XLNT_API timedelta /// /// Returns a timedelta from a number representing the factional number of days elapsed. /// - static timedelta from_number(long double number); + static timedelta from_number(double number); /// /// Constructs a timedelta equal to zero. @@ -53,7 +53,7 @@ struct XLNT_API timedelta /// /// Returns a numeric representation of this timedelta as a fractional number of days. /// - long double to_number() const; + double to_number() const; /// /// The days diff --git a/source/cell/cell.cpp b/source/cell/cell.cpp index a800db16..19c29272 100644 --- a/source/cell/cell.cpp +++ b/source/cell/cell.cpp @@ -56,17 +56,17 @@ namespace { -std::pair cast_numeric(const std::string &s) +std::pair cast_numeric(const std::string &s) { auto str_end = static_cast(nullptr); auto result = std::strtold(s.c_str(), &str_end); return (str_end != s.c_str() + s.size()) - ? std::make_pair(false, 0.0L) + ? std::make_pair(false, 0.0) : std::make_pair(true, result); } -std::pair cast_percentage(const std::string &s) +std::pair cast_percentage(const std::string &s) { if (s.back() == '%') { @@ -78,7 +78,7 @@ std::pair cast_percentage(const std::string &s) } } - return {false, 0}; + return {false, 0.0}; } std::pair cast_time(const std::string &s) @@ -206,48 +206,42 @@ void cell::value(std::nullptr_t) void cell::value(bool boolean_value) { d_->type_ = type::boolean; - d_->value_numeric_ = boolean_value ? 1.0L : 0.0L; + d_->value_numeric_ = boolean_value ? 1.0 : 0.0; } void cell::value(int int_value) { - d_->value_numeric_ = static_cast(int_value); + d_->value_numeric_ = static_cast(int_value); d_->type_ = type::number; } void cell::value(unsigned int int_value) { - d_->value_numeric_ = static_cast(int_value); + d_->value_numeric_ = static_cast(int_value); d_->type_ = type::number; } void cell::value(long long int int_value) { - d_->value_numeric_ = static_cast(int_value); + d_->value_numeric_ = static_cast(int_value); d_->type_ = type::number; } void cell::value(unsigned long long int int_value) { - d_->value_numeric_ = static_cast(int_value); + d_->value_numeric_ = static_cast(int_value); d_->type_ = type::number; } void cell::value(float float_value) { - d_->value_numeric_ = static_cast(float_value); + d_->value_numeric_ = static_cast(float_value); d_->type_ = type::number; } void cell::value(double float_value) { - d_->value_numeric_ = static_cast(float_value); - d_->type_ = type::number; -} - -void cell::value(long double d) -{ - d_->value_numeric_ = d; + d_->value_numeric_ = static_cast(float_value); d_->type_ = type::number; } @@ -261,7 +255,7 @@ void cell::value(const rich_text &text) check_string(text.plain_text()); d_->type_ = type::shared_string; - d_->value_numeric_ = static_cast(workbook().add_shared_string(text)); + d_->value_numeric_ = static_cast(workbook().add_shared_string(text)); } void cell::value(const char *c) @@ -574,12 +568,6 @@ XLNT_API double cell::value() const return static_cast(d_->value_numeric_); } -template <> -XLNT_API long double cell::value() const -{ - return d_->value_numeric_; -} - template <> XLNT_API time cell::value() const { @@ -672,14 +660,14 @@ std::string cell::to_string() const return ""; case cell::type::date: case cell::type::number: - return nf.format(value(), base_date()); + return nf.format(value(), base_date()); case cell::type::inline_string: case cell::type::shared_string: case cell::type::formula_string: case cell::type::error: return nf.format(value()); case cell::type::boolean: - return value() == 0.L ? "FALSE" : "TRUE"; + return value() == 0.0 ? "FALSE" : "TRUE"; } return ""; diff --git a/source/detail/implementations/cell_impl.hpp b/source/detail/implementations/cell_impl.hpp index fefc121f..fcf4a33c 100644 --- a/source/detail/implementations/cell_impl.hpp +++ b/source/detail/implementations/cell_impl.hpp @@ -51,7 +51,7 @@ struct cell_impl bool is_merged_; rich_text value_text_; - long double value_numeric_; + double value_numeric_; optional formula_; optional hyperlink_; diff --git a/source/detail/number_format/number_formatter.cpp b/source/detail/number_format/number_formatter.cpp index 0b799787..e002f3f6 100644 --- a/source/detail/number_format/number_formatter.cpp +++ b/source/detail/number_format/number_formatter.cpp @@ -83,7 +83,7 @@ void unhandled_case(bool error) namespace xlnt { namespace detail { -bool format_condition::satisfied_by(long double number) const +bool format_condition::satisfied_by(double number) const { switch (type) { @@ -1075,7 +1075,7 @@ number_formatter::number_formatter(const std::string &format_string, xlnt::calen format_ = parser_.result(); } -std::string number_formatter::format_number(long double number) +std::string number_formatter::format_number(double number) { if (format_[0].has_condition) { @@ -1154,7 +1154,7 @@ std::string number_formatter::format_text(const std::string &text) return format_text(format_[3], text); } -std::string number_formatter::fill_placeholders(const format_placeholders &p, long double number) +std::string number_formatter::fill_placeholders(const format_placeholders &p, double number) { std::string result; @@ -1230,7 +1230,7 @@ std::string number_formatter::fill_placeholders(const format_placeholders &p, lo else if (p.type == format_placeholders::placeholders_type::fractional_part) { auto fractional_part = number - integer_part; - result = std::fabs(fractional_part) < std::numeric_limits::min() + result = std::fabs(fractional_part) < std::numeric_limits::min() ? std::string(".") : std::to_string(fractional_part).substr(1); @@ -1259,7 +1259,7 @@ std::string number_formatter::fill_placeholders(const format_placeholders &p, lo } std::string number_formatter::fill_scientific_placeholders(const format_placeholders &integer_part, - const format_placeholders &fractional_part, const format_placeholders &exponent_part, long double number) + const format_placeholders &fractional_part, const format_placeholders &exponent_part, double number) { std::size_t logarithm = 0; @@ -1312,7 +1312,7 @@ std::string number_formatter::fill_scientific_placeholders(const format_placehol } std::string number_formatter::fill_fraction_placeholders(const format_placeholders & /*numerator*/, - const format_placeholders &denominator, long double number, bool /*improper*/) + const format_placeholders &denominator, double number, bool /*improper*/) { auto fractional_part = number - static_cast(number); auto original_fractional_part = fractional_part; @@ -1337,7 +1337,7 @@ std::string number_formatter::fill_fraction_placeholders(const format_placeholde { auto numerator_full = original_fractional_part * i; auto numerator_rounded = static_cast(std::round(numerator_full)); - auto difference = std::fabs(original_fractional_part - (numerator_rounded / static_cast(i))); + auto difference = std::fabs(original_fractional_part - (numerator_rounded / static_cast(i))); if (difference < best_difference) { @@ -1350,7 +1350,7 @@ std::string number_formatter::fill_fraction_placeholders(const format_placeholde return std::to_string(numerator_rounded) + "/" + std::to_string(best_denominator); } -std::string number_formatter::format_number(const format_code &format, long double number) +std::string number_formatter::format_number(const format_code &format, double number) { static const std::vector *month_names = new std::vector{"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; diff --git a/source/detail/number_format/number_formatter.hpp b/source/detail/number_format/number_formatter.hpp index de86d405..02ede6b5 100644 --- a/source/detail/number_format/number_formatter.hpp +++ b/source/detail/number_format/number_formatter.hpp @@ -222,9 +222,9 @@ struct XLNT_API format_condition greater_or_equal } type = condition_type::not_equal; - long double value = 0; + double value = 0.0; - bool satisfied_by(long double number) const; + bool satisfied_by(double number) const; }; struct format_placeholders @@ -352,17 +352,17 @@ class XLNT_API number_formatter { public: number_formatter(const std::string &format_string, xlnt::calendar calendar); - std::string format_number(long double number); + std::string format_number(double number); std::string format_text(const std::string &text); private: - std::string fill_placeholders(const format_placeholders &p, long double number); + std::string fill_placeholders(const format_placeholders &p, double number); std::string fill_fraction_placeholders(const format_placeholders &numerator, - const format_placeholders &denominator, long double number, bool improper); + const format_placeholders &denominator, double number, bool improper); std::string fill_scientific_placeholders(const format_placeholders &integer_part, const format_placeholders &fractional_part, const format_placeholders &exponent_part, - long double number); - std::string format_number(const format_code &format, long double number); + double number); + std::string format_number(const format_code &format, double number); std::string format_text(const format_code &format, const std::string &text); number_format_parser parser_; diff --git a/source/detail/serialization/xlsx_consumer.cpp b/source/detail/serialization/xlsx_consumer.cpp index 291dee55..cb9e19b4 100644 --- a/source/detail/serialization/xlsx_consumer.cpp +++ b/source/detail/serialization/xlsx_consumer.cpp @@ -110,7 +110,7 @@ struct number_converter stream.imbue(std::locale("C")); } - long double stold(const std::string &s) + double stold(const std::string &s) { stream.str(s); stream.clear(); @@ -119,7 +119,7 @@ struct number_converter }; std::istringstream stream; - long double result; + double result; }; } // namespace diff --git a/source/detail/serialization/xlsx_producer.cpp b/source/detail/serialization/xlsx_producer.cpp index 9904274b..2fad2f5c 100644 --- a/source/detail/serialization/xlsx_producer.cpp +++ b/source/detail/serialization/xlsx_producer.cpp @@ -47,9 +47,9 @@ namespace { /// /// Returns true if d is exactly equal to an integer. /// -bool is_integral(long double d) +bool is_integral(double d) { - return std::fabs(d - static_cast(static_cast(d))) == 0.L; + return std::fabs(d - static_cast(static_cast(d))) == 0.L; } std::vector> core_property_namespace(xlnt::core_property type) @@ -2330,15 +2330,15 @@ void xlsx_producer::write_worksheet(const relationship &rel) case cell::type::number: write_start_element(xmlns, "v"); - if (is_integral(cell.value())) + if (is_integral(cell.value())) { - write_characters(static_cast(cell.value())); + write_characters(static_cast(cell.value())); } else { std::stringstream ss; ss.precision(20); - ss << cell.value(); + ss << cell.value(); write_characters(ss.str()); } diff --git a/source/styles/number_format.cpp b/source/styles/number_format.cpp index df0bbcc3..270a6875 100644 --- a/source/styles/number_format.cpp +++ b/source/styles/number_format.cpp @@ -344,7 +344,7 @@ std::string number_format::format(const std::string &text) const return detail::number_formatter(format_string_, calendar::windows_1900).format_text(text); } -std::string number_format::format(long double number, calendar base_date) const +std::string number_format::format(double number, calendar base_date) const { return detail::number_formatter(format_string_, base_date).format_number(number); } diff --git a/source/utils/datetime.cpp b/source/utils/datetime.cpp index 1f85487b..c4955f4f 100644 --- a/source/utils/datetime.cpp +++ b/source/utils/datetime.cpp @@ -43,7 +43,7 @@ std::string fill(const std::string &string, std::size_t length = 2) namespace xlnt { -datetime datetime::from_number(long double raw_time, calendar base_date) +datetime datetime::from_number(double raw_time, calendar base_date) { auto date_part = date::from_number(static_cast(raw_time), base_date); auto time_part = time::from_number(raw_time); @@ -54,13 +54,19 @@ datetime datetime::from_number(long double raw_time, calendar base_date) bool datetime::operator==(const datetime &comparand) const { - return year == comparand.year && month == comparand.month && day == comparand.day && hour == comparand.hour - && minute == comparand.minute && second == comparand.second && microsecond == comparand.microsecond; + return year == comparand.year + && month == comparand.month + && day == comparand.day + && hour == comparand.hour + && minute == comparand.minute + && second == comparand.second + && microsecond == comparand.microsecond; } -long double datetime::to_number(calendar base_date) const +double datetime::to_number(calendar base_date) const { - return date(year, month, day).to_number(base_date) + time(hour, minute, second, microsecond).to_number(); + return date(year, month, day).to_number(base_date) + + time(hour, minute, second, microsecond).to_number(); } std::string datetime::to_string() const diff --git a/source/utils/time.cpp b/source/utils/time.cpp index bfed709e..4c3365ac 100644 --- a/source/utils/time.cpp +++ b/source/utils/time.cpp @@ -43,7 +43,7 @@ std::tm safe_localtime(std::time_t raw_time) namespace xlnt { -time time::from_number(long double raw_time) +time time::from_number(double raw_time) { time result; @@ -110,7 +110,7 @@ time::time(const std::string &time_string) } } -long double time::to_number() const +double time::to_number() const { std::uint64_t microseconds = static_cast(microsecond); microseconds += static_cast(second * 1e6); diff --git a/source/utils/timedelta.cpp b/source/utils/timedelta.cpp index 53e8ca27..0ae9c7d6 100644 --- a/source/utils/timedelta.cpp +++ b/source/utils/timedelta.cpp @@ -37,27 +37,27 @@ timedelta::timedelta(int days_, int hours_, int minutes_, int seconds_, int micr { } -long double timedelta::to_number() const +double timedelta::to_number() const { std::uint64_t total_microseconds = static_cast(microseconds); total_microseconds += static_cast(seconds * 1e6); total_microseconds += static_cast(minutes * 1e6 * 60); auto microseconds_per_hour = static_cast(1e6) * 60 * 60; total_microseconds += static_cast(hours) * microseconds_per_hour; - auto number = total_microseconds / (24.0L * microseconds_per_hour); + auto number = total_microseconds / (24.0 * microseconds_per_hour); auto hundred_billion = static_cast(1e9) * 100; - number = std::floor(number * hundred_billion + 0.5L) / hundred_billion; + number = std::floor(number * hundred_billion + 0.5) / hundred_billion; number += days; return number; } -timedelta timedelta::from_number(long double raw_time) +timedelta timedelta::from_number(double raw_time) { timedelta result; result.days = static_cast(raw_time); - long double fractional_part = raw_time - result.days; + double fractional_part = raw_time - result.days; fractional_part *= 24; result.hours = static_cast(fractional_part); diff --git a/source/worksheet/worksheet.cpp b/source/worksheet/worksheet.cpp index 78254e70..30e3cc0d 100644 --- a/source/worksheet/worksheet.cpp +++ b/source/worksheet/worksheet.cpp @@ -671,7 +671,7 @@ bool worksheet::compare(const worksheet &other, bool reference) const } if (this_cell.data_type() == xlnt::cell::type::number - && std::fabs(this_cell.value() - other_cell.value()) > 0.L) + && std::fabs(this_cell.value() - other_cell.value()) > 0.0) { return false; } diff --git a/tests/cell/cell_test_suite.hpp b/tests/cell/cell_test_suite.hpp index e7611ab5..0c72645f 100644 --- a/tests/cell/cell_test_suite.hpp +++ b/tests/cell/cell_test_suite.hpp @@ -76,7 +76,7 @@ private: auto cell = ws.cell("A1"); cell.value("4.2", true); - xlnt_assert_delta(cell.value(), 4.2L, 1E-9); + xlnt_assert_delta(cell.value(), 4.2, 1E-9); cell.value("-42.000", true); xlnt_assert(cell.value() == -42); @@ -85,10 +85,10 @@ private: xlnt_assert(cell.value() == 0); cell.value("0.9999", true); - xlnt_assert(cell.value() == 0.9999L); + xlnt_assert(cell.value() == 0.9999); cell.value("99E-02", true); - xlnt_assert(cell.value() == 0.99L); + xlnt_assert(cell.value() == 0.99); cell.value("4", true); xlnt_assert(cell.value() == 4); @@ -100,7 +100,7 @@ private: xlnt_assert(cell.value() == 200); cell.value("3.1%", true); - xlnt_assert_delta(cell.value(), 0.031L, 1E-9); + xlnt_assert_delta(cell.value(), 0.031, 1E-9); cell.value("03:40:16", true); xlnt_assert(cell.value() == xlnt::time(3, 40, 16)); @@ -256,7 +256,7 @@ private: cell.value(xlnt::datetime(2010, 7, 13, 6, 37, 41)); xlnt_assert(cell.data_type() == xlnt::cell::type::number); - xlnt_assert_delta(cell.value(), 40372.27616898148L, 1E-9); + xlnt_assert_delta(cell.value(), 40372.27616898148, 1E-9); xlnt_assert(cell.is_date()); xlnt_assert(cell.number_format().format_string() == "yyyy-mm-dd h:mm:ss"); } @@ -269,7 +269,7 @@ private: cell.value(xlnt::date(2010, 7, 13)); xlnt_assert(cell.data_type() == xlnt::cell::type::number); - xlnt_assert(cell.value() == 40372.L); + xlnt_assert(cell.value() == 40372.0); xlnt_assert(cell.is_date()); xlnt_assert(cell.number_format().format_string() == "yyyy-mm-dd"); } @@ -282,7 +282,7 @@ private: cell.value(xlnt::time(1, 3)); xlnt_assert(cell.data_type() == xlnt::cell::type::number); - xlnt_assert_delta(cell.value(), 0.04375L, 1E-9); + xlnt_assert_delta(cell.value(), 0.04375, 1E-9); xlnt_assert(cell.is_date()); xlnt_assert(cell.number_format().format_string() == "h:mm:ss"); } @@ -356,7 +356,7 @@ private: cell.value(xlnt::timedelta(1, 3, 0, 0, 0)); - xlnt_assert(cell.value() == 1.125); + xlnt_assert(cell.value() == 1.125); xlnt_assert(cell.data_type() == xlnt::cell::type::number); xlnt_assert(!cell.is_date()); xlnt_assert(cell.number_format().format_string() == "[hh]:mm:ss"); @@ -612,11 +612,8 @@ private: cell.value(static_cast(3.14)); xlnt_assert_delta(cell.value(), 3.14, 0.001); - cell.value(static_cast(4.1415)); - xlnt_assert_equals(cell.value(), 4.1415); - - cell.value(static_cast(3.141592)); - xlnt_assert_equals(cell.value(), 3.141592); + cell.value(static_cast(3.141592)); + xlnt_assert_equals(cell.value(), 3.141592); auto cell2 = ws.cell("A2"); cell2.value(std::string(100000, 'a')); diff --git a/tests/styles/number_format_test_suite.hpp b/tests/styles/number_format_test_suite.hpp index 3d5a37cc..ca378ddb 100644 --- a/tests/styles/number_format_test_suite.hpp +++ b/tests/styles/number_format_test_suite.hpp @@ -769,9 +769,9 @@ public: void format_and_test(const xlnt::number_format &nf, const std::array &expect) { - long double positive = 42503.1234; - long double negative = -1 * positive; - long double zero = 0; + double positive = 42503.1234; + double negative = -1 * positive; + double zero = 0; const std::string text = "text"; xlnt::calendar calendar = xlnt::calendar::windows_1900; diff --git a/tests/utils/timedelta_test_suite.hpp b/tests/utils/timedelta_test_suite.hpp index de77af7f..4828b0eb 100644 --- a/tests/utils/timedelta_test_suite.hpp +++ b/tests/utils/timedelta_test_suite.hpp @@ -51,7 +51,7 @@ public: void test_round_trip() { - long double time = 3.14159265359L; + double time = 3.14159265359; auto td = xlnt::timedelta::from_number(time); auto time_rt = td.to_number(); xlnt_assert_delta(time, time_rt, 1E-9); @@ -59,8 +59,8 @@ public: void test_to_number() { - xlnt::timedelta td(1, 1, 1, 1, 1); - xlnt_assert_delta(td.to_number(), 1.0423726852L, 1E-9); + xlnt::timedelta td(1, 1, 1, 1, 1); + xlnt_assert_delta(td.to_number(), 1.0423726852L, 1E-9); } void test_carry() diff --git a/tests/workbook/serialization_test_suite.hpp b/tests/workbook/serialization_test_suite.hpp index a572d46e..2c077e08 100644 --- a/tests/workbook/serialization_test_suite.hpp +++ b/tests/workbook/serialization_test_suite.hpp @@ -120,9 +120,6 @@ public: ws.cell("A14").value("number (double)"); ws.cell("B14").value(std::numeric_limits::max()); - ws.cell("A15").value("number (long double)"); - ws.cell("B15").value(std::numeric_limits::max()); - ws.cell("A16").value("text (char *)"); ws.cell("B16").value("string");