differential code coverage report with master
Current view: top level - source/cell - cell.cpp (source / functions) Coverage Total Hit UBC CBC
Current: coverage.info Lines: 90.7 % 475 431 44 431
Current Date: 2025-12-07 02:01:22 Functions: 87.9 % 116 102 14 102
Baseline: coverage_master.info Branches: 82.2 % 512 421 182 842
Baseline Date: 2025-12-07 02:01:21

             Branch data    TLA  Line data    Source code
       1                 :                : // Copyright (c) 2014-2022 Thomas Fussell
       2                 :                : // Copyright (c) 2010-2015 openpyxl
       3                 :                : // Copyright (c) 2024-2025 xlnt-community
       4                 :                : //
       5                 :                : // Permission is hereby granted, free of charge, to any person obtaining a copy
       6                 :                : // of this software and associated documentation files (the "Software"), to deal
       7                 :                : // in the Software without restriction, including without limitation the rights
       8                 :                : // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       9                 :                : // copies of the Software, and to permit persons to whom the Software is
      10                 :                : // furnished to do so, subject to the following conditions:
      11                 :                : //
      12                 :                : // The above copyright notice and this permission notice shall be included in
      13                 :                : // all copies or substantial portions of the Software.
      14                 :                : //
      15                 :                : // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16                 :                : // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17                 :                : // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      18                 :                : // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19                 :                : // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      20                 :                : // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      21                 :                : // THE SOFTWARE
      22                 :                : //
      23                 :                : // @license: http://www.opensource.org/licenses/mit-license.php
      24                 :                : // @author: see AUTHORS file
      25                 :                : 
      26                 :                : #include <algorithm>
      27                 :                : #include <cassert>
      28                 :                : #include <cmath>
      29                 :                : 
      30                 :                : #include <xlnt/cell/cell.hpp>
      31                 :                : #include <xlnt/cell/cell_reference.hpp>
      32                 :                : #include <xlnt/cell/comment.hpp>
      33                 :                : #include <xlnt/cell/hyperlink.hpp>
      34                 :                : #include <xlnt/cell/rich_text.hpp>
      35                 :                : #include <xlnt/packaging/manifest.hpp>
      36                 :                : #include <xlnt/packaging/relationship.hpp>
      37                 :                : #include <xlnt/styles/alignment.hpp>
      38                 :                : #include <xlnt/styles/border.hpp>
      39                 :                : #include <xlnt/styles/color.hpp>
      40                 :                : #include <xlnt/styles/fill.hpp>
      41                 :                : #include <xlnt/styles/font.hpp>
      42                 :                : #include <xlnt/styles/format.hpp>
      43                 :                : #include <xlnt/styles/number_format.hpp>
      44                 :                : #include <xlnt/styles/protection.hpp>
      45                 :                : #include <xlnt/styles/style.hpp>
      46                 :                : #include <xlnt/utils/date.hpp>
      47                 :                : #include <xlnt/utils/datetime.hpp>
      48                 :                : #include <xlnt/utils/exceptions.hpp>
      49                 :                : #include <xlnt/utils/time.hpp>
      50                 :                : #include <xlnt/utils/timedelta.hpp>
      51                 :                : #include <xlnt/workbook/workbook.hpp>
      52                 :                : #include <xlnt/worksheet/column_properties.hpp>
      53                 :                : #include <xlnt/worksheet/phonetic_pr.hpp>
      54                 :                : #include <xlnt/worksheet/row_properties.hpp>
      55                 :                : #include <xlnt/worksheet/worksheet.hpp>
      56                 :                : #include <detail/implementations/cell_impl.hpp>
      57                 :                : #include <detail/implementations/format_impl.hpp>
      58                 :                : #include <detail/implementations/hyperlink_impl.hpp>
      59                 :                : #include <detail/implementations/stylesheet.hpp>
      60                 :                : #include <detail/implementations/worksheet_impl.hpp>
      61                 :                : #include <detail/serialization/serialisation_helpers.hpp>
      62                 :                : 
      63                 :                : namespace {
      64                 :                : 
      65                 :CBC          11 : std::pair<bool, double> cast_numeric(const std::string &s)
      66                 :                : {
      67                 :             11 :     size_t len_convert = 0;
      68            [ + ]:             11 :     double result = xlnt::detail::deserialise(s, &len_convert);
      69                 :             11 :     return (len_convert != s.size())
      70         [ +  + ]:             11 :         ? std::make_pair(false, 0.0)
      71                 :             11 :         : std::make_pair(true, result);
      72                 :                : }
      73                 :                : 
      74                 :             14 : std::pair<bool, double> cast_percentage(const std::string &s)
      75                 :                : {
      76         [ +  + ]:             14 :     if (s.back() == '%')
      77                 :                :     {
      78         [ +  + ]:              1 :         auto number = cast_numeric(s.substr(0, s.size() - 1));
      79                 :                : 
      80         [ +  - ]:              1 :         if (number.first)
      81                 :                :         {
      82                 :              1 :             return {true, number.second / 100};
      83                 :                :         }
      84                 :                :     }
      85                 :                : 
      86                 :             13 :     return {false, 0.0};
      87                 :                : }
      88                 :                : 
      89                 :             13 : std::pair<bool, xlnt::time> cast_time(const std::string &s)
      90                 :                : {
      91            [ + ]:             13 :     xlnt::time result;
      92                 :                : 
      93                 :             13 :     std::vector<std::string> time_components;
      94                 :             13 :     std::size_t prev = 0;
      95                 :             13 :     auto colon_index = s.find(':');
      96                 :                : 
      97         [ +  + ]:             18 :     while (colon_index != std::string::npos)
      98                 :                :     {
      99         [ +  + ]:              5 :         time_components.push_back(s.substr(prev, colon_index - prev));
     100                 :              5 :         prev = colon_index + 1;
     101                 :              5 :         colon_index = s.find(':', colon_index + 1);
     102                 :                :     }
     103                 :                : 
     104         [ +  + ]:             13 :     time_components.push_back(s.substr(prev, colon_index - prev));
     105                 :                : 
     106   [ +  +  -  +  :             13 :     if (time_components.size() < 2 || time_components.size() > 3)
                   +  + ]
     107                 :                :     {
     108                 :              9 :         return {false, result};
     109                 :                :     }
     110                 :                : 
     111                 :              4 :     std::vector<double> numeric_components;
     112                 :                : 
     113         [ +  + ]:             12 :     for (const auto & component : time_components)
     114                 :                :     {
     115   [ +  +  +  -  :              9 :         if (component.empty() || (component.substr(0, component.find('.')).size() > 2))
          +  +  +  +  +  
                   -  - ]
     116                 :                :         {
     117                 :              1 :             return {false, result};
     118                 :                :         }
     119                 :                : 
     120         [ +  + ]:             34 :         for (auto d : component)
     121                 :                :         {
     122   [ +  +  -  +  :             26 :             if (!(d >= '0' && d <= '9') && d != '.')
                   -  + ]
     123                 :                :             {
     124                 :UBC           0 :                 return {false, result};
     125                 :                :             }
     126                 :                :         }
     127            [ + ]:CBC           8 :         auto numeric = xlnt::detail::deserialise(component);
     128                 :                : 
     129            [ + ]:              8 :         numeric_components.push_back(numeric);
     130                 :                :     }
     131                 :                : 
     132                 :              3 :     result.hour = static_cast<int>(numeric_components[0]);
     133                 :              3 :     result.minute = static_cast<int>(numeric_components[1]);
     134                 :                : 
     135         [ +  + ]:              3 :     if (std::fabs(static_cast<double>(result.minute) - numeric_components[1]) > std::numeric_limits<double>::epsilon())
     136                 :                :     {
     137                 :              1 :         result.minute = result.hour;
     138                 :              1 :         result.hour = 0;
     139                 :              1 :         result.second = static_cast<int>(numeric_components[1]);
     140                 :              1 :         result.microsecond = static_cast<int>((numeric_components[1] - result.second) * 1E6);
     141                 :                :     }
     142         [ +  + ]:              2 :     else if (numeric_components.size() > 2)
     143                 :                :     {
     144                 :              1 :         result.second = static_cast<int>(numeric_components[2]);
     145                 :              1 :         result.microsecond = static_cast<int>((numeric_components[2] - result.second) * 1E6);
     146                 :                :     }
     147                 :                : 
     148                 :              3 :     return {true, result};
     149                 :             13 : }
     150                 :                : 
     151                 :                : } // namespace
     152                 :                : 
     153                 :                : namespace xlnt {
     154                 :                : 
     155                 :              1 : const std::unordered_map<std::string, int> &cell::error_codes()
     156                 :                : {
     157                 :                :     static const auto codes = std::unordered_map<std::string, int>{
     158                 :UBC           0 :         {"#NULL!", 0},
     159                 :              0 :         {"#DIV/0!", 1},
     160                 :              0 :         {"#VALUE!", 2},
     161                 :              0 :         {"#REF!", 3},
     162                 :              0 :         {"#NAME?", 4},
     163                 :              0 :         {"#NUM!", 5},
     164   [ +  -  +  -  :CBC          10 :         {"#N/A!", 6}};
          +  +  +  -  -  
                   -  - ]
     165                 :                : 
     166                 :              1 :     return codes;
     167   [ +  +  +  +  :              1 : }
          +  +  +  -  -  
                   -  - ]
     168                 :                : 
     169                 :            613 : std::string cell::check_string(const std::string &to_check)
     170                 :                : {
     171                 :                :     // so we can modify it
     172                 :            613 :     std::string s = to_check;
     173                 :                : 
     174         [ +  + ]:            613 :     if (s.size() == 0)
     175                 :                :     {
     176                 :              2 :         return s;
     177                 :                :     }
     178         [ +  + ]:            611 :     else if (s.size() > 32767)
     179                 :                :     {
     180            [ + ]:              1 :         s = s.substr(0, 32767); // max string length in Excel
     181                 :                :     }
     182                 :                : 
     183         [ +  + ]:          68353 :     for (char c : s)
     184                 :                :     {
     185   [ +  -  +  +  :          67771 :         if (c >= 0 && (c <= 8 || c == 11 || c == 12 || (c >= 14 && c <= 31)))
          +  +  +  +  +  
                +  +  + ]
     186                 :                :         {
     187            [ + ]:             29 :             throw illegal_character(c);
     188                 :                :         }
     189                 :                :     }
     190                 :                : 
     191                 :            582 :     return s;
     192                 :             29 : }
     193                 :                : 
     194                 :           3264 : cell::cell(detail::cell_impl *d)
     195                 :           3264 :     : d_(d)
     196                 :                : {
     197                 :           3264 : }
     198                 :                : 
     199                 :            957 : bool cell::garbage_collectible() const
     200                 :                : {
     201                 :            957 :     return d_->is_garbage_collectible();
     202                 :                : }
     203                 :                : 
     204                 :              1 : void cell::value(std::nullptr_t)
     205                 :                : {
     206                 :              1 :     clear_value();
     207                 :              1 : }
     208                 :                : 
     209                 :             10 : void cell::value(bool boolean_value)
     210                 :                : {
     211                 :             10 :     d_->type_ = type::boolean;
     212         [ +  + ]:             10 :     d_->value_numeric_ = boolean_value ? 1.0 : 0.0;
     213                 :             10 : }
     214                 :                : 
     215                 :             14 : void cell::value(int int_value)
     216                 :                : {
     217                 :             14 :     d_->value_numeric_ = static_cast<double>(int_value);
     218                 :             14 :     d_->type_ = type::number;
     219                 :             14 : }
     220                 :                : 
     221                 :              2 : void cell::value(unsigned int int_value)
     222                 :                : {
     223                 :              2 :     d_->value_numeric_ = static_cast<double>(int_value);
     224                 :              2 :     d_->type_ = type::number;
     225                 :              2 : }
     226                 :                : 
     227                 :              2 : void cell::value(long long int int_value)
     228                 :                : {
     229                 :              2 :     d_->value_numeric_ = static_cast<double>(int_value);
     230                 :              2 :     d_->type_ = type::number;
     231                 :              2 : }
     232                 :                : 
     233                 :              2 : void cell::value(unsigned long long int int_value)
     234                 :                : {
     235                 :              2 :     d_->value_numeric_ = static_cast<double>(int_value);
     236                 :              2 :     d_->type_ = type::number;
     237                 :              2 : }
     238                 :                : 
     239                 :              2 : void cell::value(float float_value)
     240                 :                : {
     241                 :              2 :     d_->value_numeric_ = static_cast<double>(float_value);
     242                 :              2 :     d_->type_ = type::number;
     243                 :              2 : }
     244                 :                : 
     245                 :              6 : void cell::value(double float_value)
     246                 :                : {
     247                 :              6 :     d_->value_numeric_ = static_cast<double>(float_value);
     248                 :              6 :     d_->type_ = type::number;
     249                 :              6 : }
     250                 :                : 
     251                 :            321 : void cell::value(const std::string &s)
     252                 :                : {
     253      [ +  +  + ]:            321 :     value(rich_text(check_string(s)));
     254                 :            292 : }
     255                 :                : 
     256                 :            292 : void cell::value(const rich_text &text)
     257                 :                : {
     258         [ +  + ]:            292 :     check_string(text.plain_text());
     259                 :                : 
     260                 :            292 :     d_->type_ = type::shared_string;
     261         [ +  + ]:            292 :     d_->value_numeric_ = static_cast<double>(workbook().add_shared_string(text));
     262                 :            292 : }
     263                 :                : 
     264                 :            120 : void cell::value(const char *c)
     265                 :                : {
     266         [ +  + ]:            120 :     value(std::string(c));
     267                 :            120 : }
     268                 :                : 
     269                 :              1 : void cell::value(const cell c)
     270                 :                : {
     271                 :              1 :     d_->type_ = c.d_->type_;
     272                 :              1 :     d_->value_numeric_ = c.d_->value_numeric_;
     273                 :              1 :     d_->value_text_ = c.d_->value_text_;
     274                 :              1 :     d_->hyperlink_ = c.d_->hyperlink_;
     275                 :              1 :     d_->formula_ = c.d_->formula_;
     276                 :              1 :     d_->format_ = c.d_->format_;
     277                 :              1 : }
     278                 :                : 
     279                 :              3 : void cell::value(const date &d)
     280                 :                : {
     281                 :              3 :     d_->type_ = type::number;
     282                 :              3 :     d_->value_numeric_ = d.to_number(base_date());
     283         [ +  + ]:              3 :     number_format(number_format::date_yyyymmdd2());
     284                 :              3 : }
     285                 :                : 
     286                 :              5 : void cell::value(const datetime &d)
     287                 :                : {
     288                 :              5 :     d_->type_ = type::number;
     289                 :              5 :     d_->value_numeric_ = d.to_number(base_date());
     290         [ +  + ]:              5 :     number_format(number_format::date_datetime());
     291                 :              5 : }
     292                 :                : 
     293                 :              2 : void cell::value(const time &t)
     294                 :                : {
     295                 :              2 :     d_->type_ = type::number;
     296                 :              2 :     d_->value_numeric_ = t.to_number();
     297         [ +  + ]:              2 :     number_format(number_format::date_time6());
     298                 :              2 : }
     299                 :                : 
     300                 :              2 : void cell::value(const timedelta &t)
     301                 :                : {
     302                 :              2 :     d_->type_ = type::number;
     303                 :              2 :     d_->value_numeric_ = t.to_number();
     304      [ +  +  + ]:              2 :     number_format(xlnt::number_format("[hh]:mm:ss"));
     305                 :              2 : }
     306                 :                : 
     307                 :              7 : row_t cell::row() const
     308                 :                : {
     309                 :              7 :     return d_->row_;
     310                 :                : }
     311                 :                : 
     312                 :             39 : column_t cell::column() const
     313                 :                : {
     314                 :             39 :     return d_->column_;
     315                 :                : }
     316                 :                : 
     317                 :              1 : column_t::index_t cell::column_index() const
     318                 :                : {
     319                 :              1 :     return d_->column_.index;
     320                 :                : }
     321                 :                : 
     322                 :            774 : void cell::merged(bool merged)
     323                 :                : {
     324                 :            774 :     d_->is_merged_ = merged;
     325                 :            774 : }
     326                 :                : 
     327                 :UBC           0 : bool cell::is_merged() const
     328                 :                : {
     329                 :              0 :     return d_->is_merged_;
     330                 :                : }
     331                 :                : 
     332                 :CBC         964 : bool cell::phonetics_visible() const
     333                 :                : {
     334                 :            964 :     return d_->phonetics_visible_;
     335                 :                : }
     336                 :                : 
     337                 :              2 : void cell::show_phonetics(bool phonetics)
     338                 :                : {
     339                 :              2 :     d_->phonetics_visible_ = phonetics;
     340                 :              2 : }
     341                 :                : 
     342                 :              7 : bool cell::is_date() const
     343                 :                : {
     344                 :              7 :     return data_type() == type::number
     345         [ +  - ]:              4 :         && has_format()
     346   [ +  +  +  +  :             11 :         && number_format().is_date_format();
          +  +  +  +  -  
                      - ]
     347                 :                : }
     348                 :                : 
     349                 :           1124 : cell_reference cell::reference() const
     350                 :                : {
     351            [ + ]:           1124 :     return {d_->column_, d_->row_};
     352                 :                : }
     353                 :                : 
     354                 :             17 : bool cell::compare(const cell &other, bool compare_by_reference) const
     355                 :                : {
     356         [ +  - ]:             17 :     if (compare_by_reference)
     357                 :                :     {
     358                 :             17 :         return d_ == other.d_;
     359                 :                :     }
     360                 :                :     else
     361                 :                :     {
     362                 :UBC           0 :         return *d_ == *other.d_;
     363                 :                :     }
     364                 :                : }
     365                 :                : 
     366                 :CBC          17 : bool cell::operator==(const cell &comparand) const
     367                 :                : {
     368                 :             17 :     return compare(comparand, true);
     369                 :                : }
     370                 :                : 
     371                 :              2 : bool cell::operator!=(const cell &comparand) const
     372                 :                : {
     373                 :              2 :     return !(*this == comparand);
     374                 :                : }
     375                 :                : 
     376                 :              1 : cell &cell::operator=(const cell &rhs) = default;
     377                 :                : 
     378                 :             62 : hyperlink cell::hyperlink() const
     379                 :                : {
     380         [ +  + ]:             62 :     return xlnt::hyperlink(&d_->hyperlink_.get());
     381                 :                : }
     382                 :                : 
     383                 :             38 : void cell::hyperlink(const std::string &url, const std::string &display)
     384                 :                : {
     385         [ +  + ]:             38 :     if (url.empty())
     386                 :                :     {
     387            [ + ]:              1 :         throw invalid_parameter();
     388                 :                :     }
     389                 :                : 
     390            [ + ]:             37 :     auto ws = worksheet();
     391         [ +  + ]:             37 :     auto &manifest = ws.workbook().manifest();
     392                 :                : 
     393            [ + ]:             37 :     d_->hyperlink_ = detail::hyperlink_impl();
     394                 :                : 
     395                 :                :     // check for existing relationships
     396         [ +  + ]:             37 :     auto relationships = manifest.relationships(ws.path(), relationship_type::hyperlink);
     397            [ + ]:             37 :     auto relation = std::find_if(relationships.cbegin(), relationships.cend(),
     398                 :             57 :         [&url](xlnt::relationship rel) { return rel.target().path().string() == url; });
     399         [ +  + ]:             37 :     if (relation != relationships.end())
     400                 :                :     {
     401         [ +  + ]:             30 :         d_->hyperlink_.get().relationship = *relation;
     402                 :                :     }
     403                 :                :     else
     404                 :                :     { // register a new relationship
     405                 :                :         auto rel_id = manifest.register_relationship(
     406      [ +  +  + ]:             14 :             uri(ws.path().string()),
     407                 :                :             relationship_type::hyperlink,
     408            [ + ]:             14 :             uri(url),
     409            [ + ]:              7 :             target_mode::external);
     410                 :                :         // TODO: make manifest::register_relationship return the created relationship instead of rel id
     411      [ +  +  + ]:              7 :         d_->hyperlink_.get().relationship = manifest.relationship(ws.path(), rel_id);
     412                 :              7 :     }
     413                 :                :     // if a value is already present, the display string is ignored
     414         [ +  + ]:             37 :     if (has_value())
     415                 :                :     {
     416         [ +  + ]:             31 :         d_->hyperlink_.get().display.set(to_string());
     417                 :                :     }
     418                 :                :     else
     419                 :                :     {
     420   [ +  +  +  + ]:              6 :         d_->hyperlink_.get().display.set(display.empty() ? url : display);
     421      [ +  +  + ]:              6 :         value(hyperlink().display());
     422                 :                :     }
     423                 :             37 : }
     424                 :                : 
     425                 :              4 : void cell::hyperlink(xlnt::cell target, const std::string &display)
     426                 :                : {
     427                 :                :     // TODO: should this computed value be a method on a cell?
     428   [ +  +  +  +  :              4 :     const auto cell_address = target.worksheet().title() + "!" + target.reference().to_string();
                   +  + ]
     429                 :                : 
     430            [ + ]:              4 :     d_->hyperlink_ = detail::hyperlink_impl();
     431            [ + ]:              8 :     d_->hyperlink_.get().relationship = xlnt::relationship("", relationship_type::hyperlink,
     432   [ +  +  +  +  :             28 :         uri(""), uri(cell_address), target_mode::internal);
                      + ]
     433                 :                :     // if a value is already present, the display string is ignored
     434         [ +  + ]:              4 :     if (has_value())
     435                 :                :     {
     436         [ +  + ]:              1 :         d_->hyperlink_.get().display.set(to_string());
     437                 :                :     }
     438                 :                :     else
     439                 :                :     {
     440   [ +  +  +  + ]:              3 :         d_->hyperlink_.get().display.set(display.empty() ? cell_address : display);
     441      [ +  +  + ]:              3 :         value(hyperlink().display());
     442                 :                :     }
     443                 :              4 : }
     444                 :                : 
     445                 :              3 : void cell::hyperlink(xlnt::range target, const std::string &display)
     446                 :                : {
     447                 :                :     // TODO: should this computed value be a method on a cell?
     448   [ +  +  +  +  :              3 :     const auto range_address = target.target_worksheet().title() + "!" + target.reference().to_string();
                   +  + ]
     449                 :                : 
     450            [ + ]:              3 :     d_->hyperlink_ = detail::hyperlink_impl();
     451            [ + ]:              6 :     d_->hyperlink_.get().relationship = xlnt::relationship("", relationship_type::hyperlink,
     452   [ +  +  +  +  :             21 :         uri(""), uri(range_address), target_mode::internal);
                      + ]
     453                 :                : 
     454                 :                :     // if a value is already present, the display string is ignored
     455         [ +  + ]:              3 :     if (has_value())
     456                 :                :     {
     457         [ +  + ]:              1 :         d_->hyperlink_.get().display.set(to_string());
     458                 :                :     }
     459                 :                :     else
     460                 :                :     {
     461   [ +  +  +  + ]:              2 :         d_->hyperlink_.get().display.set(display.empty() ? range_address : display);
     462      [ +  +  + ]:              2 :         value(hyperlink().display());
     463                 :                :     }
     464                 :              3 : }
     465                 :                : 
     466                 :             17 : void cell::formula(const std::string &formula)
     467                 :                : {
     468         [ +  + ]:             17 :     if (formula.empty())
     469                 :                :     {
     470                 :              1 :         return clear_formula();
     471                 :                :     }
     472                 :                : 
     473         [ +  + ]:             16 :     if (formula[0] == '=')
     474                 :                :     {
     475            [ + ]:              7 :         d_->formula_ = formula.substr(1);
     476                 :                :     }
     477                 :                :     else
     478                 :                :     {
     479                 :              9 :         d_->formula_ = formula;
     480                 :                :     }
     481                 :                : 
     482         [ +  + ]:             16 :     worksheet().register_calc_chain_in_manifest();
     483                 :                : }
     484                 :                : 
     485                 :           2207 : bool cell::has_formula() const
     486                 :                : {
     487                 :           2207 :     return d_->formula_.is_set();
     488                 :                : }
     489                 :                : 
     490                 :             18 : std::string cell::formula() const
     491                 :                : {
     492                 :             18 :     return d_->formula_.get();
     493                 :                : }
     494                 :                : 
     495                 :            794 : void cell::clear_formula()
     496                 :                : {
     497         [ +  + ]:            794 :     if (has_formula())
     498                 :                :     {
     499                 :             18 :         d_->formula_.clear();
     500         [ +  + ]:             18 :         worksheet().garbage_collect_formulae();
     501                 :                :     }
     502                 :            794 : }
     503                 :                : 
     504                 :             21 : std::string cell::error() const
     505                 :                : {
     506         [ +  + ]:             21 :     if (d_->type_ != type::error)
     507                 :                :     {
     508         [ +  + ]:             21 :         throw xlnt::exception("called error() when cell type is not error");
     509                 :                :     }
     510                 :             14 :     return value<std::string>();
     511                 :                : }
     512                 :                : 
     513                 :             17 : void cell::error(const std::string &error)
     514                 :                : {
     515   [ +  +  +  +  :             17 :     if (error.length() == 0 || error[0] != '#')
                   +  + ]
     516                 :                :     {
     517            [ + ]:              2 :         throw invalid_data_type();
     518                 :                :     }
     519                 :                : 
     520                 :             15 :     d_->value_text_.plain_text(error, false);
     521                 :             15 :     d_->type_ = type::error;
     522                 :             15 : }
     523                 :                : 
     524                 :              1 : cell cell::offset(int column, int row)
     525                 :                : {
     526   [ +  +  +  + ]:              1 :     return worksheet().cell(reference().make_offset(column, row));
     527                 :                : }
     528                 :                : 
     529                 :            457 : worksheet cell::worksheet()
     530                 :                : {
     531                 :            457 :     return xlnt::worksheet(d_->parent_);
     532                 :                : }
     533                 :                : 
     534                 :            252 : const worksheet cell::worksheet() const
     535                 :                : {
     536                 :            252 :     return xlnt::worksheet(d_->parent_);
     537                 :                : }
     538                 :                : 
     539                 :            347 : workbook cell::workbook()
     540                 :                : {
     541         [ +  + ]:            347 :     return worksheet().workbook();
     542                 :                : }
     543                 :                : 
     544                 :            202 : const workbook cell::workbook() const
     545                 :                : {
     546         [ +  + ]:            202 :     return worksheet().workbook();
     547                 :                : }
     548                 :                : 
     549                 :             35 : std::pair<int, int> cell::anchor() const
     550                 :                : {
     551                 :             35 :     double left = 0;
     552                 :                : 
     553   [ +  +  +  +  :             35 :     for (column_t column_index = 1; column_index <= d_->column_ - 1; column_index++)
                   -  + ]
     554                 :                :     {
     555      [ #  #  # ]:UBC           0 :         left += worksheet().column_width(column_index);
     556                 :                :     }
     557                 :                : 
     558                 :CBC          35 :     double top = 0;
     559                 :                : 
     560         [ +  + ]:             51 :     for (row_t row_index = 1; row_index <= d_->row_ - 1; row_index++)
     561                 :                :     {
     562         [ +  + ]:             16 :         top += worksheet().row_height(row_index);
     563                 :                :     }
     564                 :                : 
     565                 :             35 :     return {static_cast<int>(left), static_cast<int>(top)};
     566                 :                : }
     567                 :                : 
     568                 :           2960 : cell::type cell::data_type() const
     569                 :                : {
     570                 :           2960 :     return d_->type_;
     571                 :                : }
     572                 :                : 
     573                 :            151 : void cell::data_type(type t)
     574                 :                : {
     575                 :            151 :     d_->type_ = t;
     576                 :            151 : }
     577                 :                : 
     578                 :             47 : number_format cell::computed_number_format() const
     579                 :                : {
     580                 :             47 :     return xlnt::number_format();
     581                 :                : }
     582                 :                : 
     583                 :UBC           0 : font cell::computed_font() const
     584                 :                : {
     585                 :              0 :     return xlnt::font();
     586                 :                : }
     587                 :                : 
     588                 :              0 : fill cell::computed_fill() const
     589                 :                : {
     590                 :              0 :     return xlnt::fill();
     591                 :                : }
     592                 :                : 
     593                 :              0 : border cell::computed_border() const
     594                 :                : {
     595                 :              0 :     return xlnt::border();
     596                 :                : }
     597                 :                : 
     598                 :              0 : alignment cell::computed_alignment() const
     599                 :                : {
     600                 :              0 :     return xlnt::alignment();
     601                 :                : }
     602                 :                : 
     603                 :              0 : protection cell::computed_protection() const
     604                 :                : {
     605            [ # ]:              0 :     return xlnt::protection();
     606                 :                : }
     607                 :                : 
     608                 :CBC         767 : void cell::clear_value()
     609                 :                : {
     610                 :            767 :     d_->value_numeric_ = 0;
     611                 :            767 :     d_->value_text_.clear();
     612                 :            767 :     d_->type_ = cell::type::empty;
     613                 :            767 :     clear_formula();
     614                 :            767 : }
     615                 :                : 
     616                 :                : template <>
     617                 :              7 : bool cell::value() const
     618                 :                : {
     619                 :              7 :     return d_->value_numeric_ != 0.0;
     620                 :                : }
     621                 :                : 
     622                 :                : template <>
     623                 :             24 : int cell::value() const
     624                 :                : {
     625                 :             24 :     return static_cast<int>(d_->value_numeric_);
     626                 :                : }
     627                 :                : 
     628                 :                : template <>
     629                 :              1 : long long int cell::value() const
     630                 :                : {
     631                 :              1 :     return static_cast<long long int>(d_->value_numeric_);
     632                 :                : }
     633                 :                : 
     634                 :                : template <>
     635                 :              1 : unsigned int cell::value() const
     636                 :                : {
     637                 :              1 :     return static_cast<unsigned int>(d_->value_numeric_);
     638                 :                : }
     639                 :                : 
     640                 :                : template <>
     641                 :              1 : unsigned long long cell::value() const
     642                 :                : {
     643                 :              1 :     return static_cast<unsigned long long>(d_->value_numeric_);
     644                 :                : }
     645                 :                : 
     646                 :                : template <>
     647                 :              1 : float cell::value() const
     648                 :                : {
     649                 :              1 :     return static_cast<float>(d_->value_numeric_);
     650                 :                : }
     651                 :                : 
     652                 :                : template <>
     653                 :             67 : double cell::value() const
     654                 :                : {
     655                 :             67 :     return static_cast<double>(d_->value_numeric_);
     656                 :                : }
     657                 :                : 
     658                 :                : template <>
     659                 :              3 : time cell::value() const
     660                 :                : {
     661                 :              3 :     return time::from_number(d_->value_numeric_);
     662                 :                : }
     663                 :                : 
     664                 :                : template <>
     665                 :UBC           0 : datetime cell::value() const
     666                 :                : {
     667                 :              0 :     return datetime::from_number(d_->value_numeric_, base_date());
     668                 :                : }
     669                 :                : 
     670                 :                : template <>
     671                 :              0 : date cell::value() const
     672                 :                : {
     673                 :              0 :     return date::from_number(static_cast<int>(d_->value_numeric_), base_date());
     674                 :                : }
     675                 :                : 
     676                 :                : template <>
     677                 :              0 : timedelta cell::value() const
     678                 :                : {
     679                 :              0 :     return timedelta::from_number(d_->value_numeric_);
     680                 :                : }
     681                 :                : 
     682                 :CBC           1 : void cell::alignment(const class alignment &alignment_)
     683                 :                : {
     684   [ -  +  -  +  :              1 :     auto new_format = has_format() ? modifiable_format() : workbook().create_format();
             +  +  -  -  
                      - ]
     685      [ +  +  + ]:              1 :     format(new_format.alignment(alignment_, optional<bool>(true)));
     686                 :              1 : }
     687                 :                : 
     688                 :              1 : void cell::border(const class border &border_)
     689                 :                : {
     690   [ -  +  -  +  :              1 :     auto new_format = has_format() ? modifiable_format() : workbook().create_format();
             +  +  -  -  
                      - ]
     691      [ +  +  + ]:              1 :     format(new_format.border(border_, optional<bool>(true)));
     692                 :              1 : }
     693                 :                : 
     694                 :             13 : void cell::fill(const class fill &fill_)
     695                 :                : {
     696   [ +  +  +  +  :             13 :     auto new_format = has_format() ? modifiable_format() : workbook().create_format();
             +  +  +  -  
                      - ]
     697      [ +  +  + ]:             13 :     format(new_format.fill(fill_, optional<bool>(true)));
     698                 :             13 : }
     699                 :                : 
     700                 :             23 : void cell::font(const class font &font_)
     701                 :                : {
     702   [ +  +  +  +  :             23 :     auto new_format = has_format() ? modifiable_format() : workbook().create_format();
             +  +  +  -  
                      - ]
     703      [ +  +  + ]:             23 :     format(new_format.font(font_, optional<bool>(true)));
     704                 :             23 : }
     705                 :                : 
     706                 :             21 : void cell::number_format(const class number_format &number_format_)
     707                 :                : {
     708   [ +  +  +  +  :             21 :     auto new_format = has_format() ? modifiable_format() : workbook().create_format();
             +  +  +  -  
                      - ]
     709      [ +  +  + ]:             21 :     format(new_format.number_format(number_format_, optional<bool>(true)));
     710                 :             21 : }
     711                 :                : 
     712                 :              1 : void cell::protection(const class protection &protection_)
     713                 :                : {
     714   [ -  +  -  +  :              1 :     auto new_format = has_format() ? modifiable_format() : workbook().create_format();
             +  +  -  -  
                      - ]
     715      [ +  +  + ]:              1 :     format(new_format.protection(protection_, optional<bool>(true)));
     716                 :              1 : }
     717                 :                : 
     718                 :                : template <>
     719                 :            211 : std::string cell::value() const
     720                 :                : {
     721         [ +  + ]:            211 :     return value<rich_text>().plain_text();
     722                 :                : }
     723                 :                : 
     724                 :                : template <>
     725                 :            214 : rich_text cell::value() const
     726                 :                : {
     727         [ +  + ]:            214 :     if (data_type() == cell::type::shared_string)
     728                 :                :     {
     729      [ +  +  + ]:            189 :         return workbook().shared_strings(static_cast<std::size_t>(d_->value_numeric_));
     730                 :                :     }
     731                 :                : 
     732                 :             25 :     return d_->value_text_;
     733                 :                : }
     734                 :                : 
     735                 :            112 : bool cell::has_value() const
     736                 :                : {
     737                 :            112 :     return d_->type_ != cell::type::empty;
     738                 :                : }
     739                 :                : 
     740                 :             47 : std::string cell::to_string() const
     741                 :                : {
     742            [ + ]:             47 :     auto nf = computed_number_format();
     743                 :                : 
     744   [ +  +  +  +  :             47 :     switch (data_type())
                      - ]
     745                 :                :     {
     746                 :              2 :     case cell::type::empty:
     747            [ + ]:              4 :         return "";
     748                 :              5 :     case cell::type::date:
     749                 :                :     case cell::type::number:
     750         [ +  + ]:              5 :         return nf.format(value<double>(), base_date());
     751                 :             36 :     case cell::type::inline_string:
     752                 :                :     case cell::type::shared_string:
     753                 :                :     case cell::type::formula_string:
     754                 :                :     case cell::type::error:
     755         [ +  + ]:             36 :         return nf.format(value<std::string>());
     756                 :              4 :     case cell::type::boolean:
     757      [ +  +  + ]:              8 :         return value<double>() == 0.0 ? "FALSE" : "TRUE";
     758                 :                :     }
     759                 :                : 
     760            [ # ]:UBC           0 :     return "";
     761                 :CBC          47 : }
     762                 :                : 
     763                 :           1051 : bool cell::has_format() const
     764                 :                : {
     765                 :           1051 :     return d_->format_.is_set();
     766                 :                : }
     767                 :                : 
     768                 :            102 : void cell::format(const class format new_format)
     769                 :                : {
     770                 :            102 :     d_->format_ = new_format.d_;
     771                 :            102 : }
     772                 :                : 
     773                 :             13 : calendar cell::base_date() const
     774                 :                : {
     775         [ +  + ]:             13 :     return workbook().base_date();
     776                 :                : }
     777                 :                : 
     778                 :              4 : bool operator==(std::nullptr_t, const cell &cell)
     779                 :                : {
     780                 :              4 :     return cell.data_type() == cell::type::empty;
     781                 :                : }
     782                 :                : 
     783                 :              2 : bool operator==(const cell &cell, std::nullptr_t)
     784                 :                : {
     785                 :              2 :     return nullptr == cell;
     786                 :                : }
     787                 :                : 
     788                 :UBC           0 : bool operator!=(std::nullptr_t, const cell &cell)
     789                 :                : {
     790                 :              0 :     return !(nullptr == cell);
     791                 :                : }
     792                 :                : 
     793                 :              0 : bool operator!=(const cell &cell, std::nullptr_t)
     794                 :                : {
     795                 :              0 :     return nullptr != cell;
     796                 :                : }
     797                 :                : 
     798                 :CBC           6 : std::ostream &operator<<(std::ostream &stream, const xlnt::cell &cell)
     799                 :                : {
     800         [ +  + ]:              6 :     return stream << cell.to_string();
     801                 :                : }
     802                 :                : 
     803                 :             23 : void cell::value(const std::string &value_string, bool infer_type)
     804                 :                : {
     805            [ + ]:             23 :     value(value_string);
     806                 :                : 
     807   [ +  -  -  +  :             23 :     if (!infer_type || value_string.empty())
                   -  + ]
     808                 :                :     {
     809                 :              9 :         return;
     810                 :                :     }
     811                 :                : 
     812   [ +  +  +  +  :             23 :     if (value_string.front() == '=' && value_string.size() > 1)
                   +  + ]
     813                 :                :     {
     814            [ + ]:              2 :         formula(value_string);
     815                 :              2 :         return;
     816                 :                :     }
     817                 :                : 
     818   [ +  +  +  -  :             21 :     if (value_string.front() == '#' && value_string.size() > 1)
                   +  + ]
     819                 :                :     {
     820            [ + ]:              7 :         error(value_string);
     821                 :              7 :         return;
     822                 :                :     }
     823                 :                : 
     824            [ + ]:             14 :     auto percentage = cast_percentage(value_string);
     825                 :                : 
     826         [ +  + ]:             14 :     if (percentage.first)
     827                 :                :     {
     828                 :              1 :         d_->value_numeric_ = percentage.second;
     829                 :              1 :         d_->type_ = cell::type::number;
     830         [ +  + ]:              1 :         number_format(xlnt::number_format::percentage());
     831                 :                :     }
     832                 :                :     else
     833                 :                :     {
     834            [ + ]:             13 :         auto time = cast_time(value_string);
     835                 :                : 
     836         [ +  + ]:             13 :         if (time.first)
     837                 :                :         {
     838                 :              3 :             d_->type_ = cell::type::number;
     839         [ +  + ]:              3 :             number_format(number_format::date_time6());
     840            [ + ]:              3 :             d_->value_numeric_ = time.second.to_number();
     841                 :                :         }
     842                 :                :         else
     843                 :                :         {
     844            [ + ]:             10 :             auto numeric = cast_numeric(value_string);
     845                 :                : 
     846         [ +  + ]:             10 :             if (numeric.first)
     847                 :                :             {
     848                 :              8 :                 d_->value_numeric_ = numeric.second;
     849                 :              8 :                 d_->type_ = cell::type::number;
     850                 :                :             }
     851                 :                :         }
     852                 :                :     }
     853                 :                : }
     854                 :                : 
     855                 :              2 : void cell::clear_format()
     856                 :                : {
     857         [ +  - ]:              2 :     if (d_->format_.is_set())
     858                 :              2 :         d_->format_.clear();
     859                 :              2 : }
     860                 :                : 
     861                 :              2 : void cell::clear_style()
     862                 :                : {
     863         [ +  - ]:              2 :     if (has_format())
     864                 :                :     {
     865         [ +  + ]:              2 :         modifiable_format().clear_style();
     866                 :                :     }
     867                 :              2 : }
     868                 :                : 
     869                 :              4 : void cell::style(const class style &new_style)
     870                 :                : {
     871   [ +  +  +  +  :              4 :     auto new_format = has_format() ? format() : workbook().create_format();
             +  +  +  -  
                      - ]
     872                 :                : 
     873         [ +  + ]:              4 :     new_format.border(new_style.border());
     874         [ +  + ]:              4 :     new_format.fill(new_style.fill());
     875         [ +  + ]:              4 :     new_format.font(new_style.font());
     876         [ +  + ]:              4 :     new_format.number_format(new_style.number_format());
     877                 :                : 
     878      [ +  +  + ]:              4 :     format(new_format.style(new_style));
     879                 :              4 : }
     880                 :                : 
     881                 :              2 : void cell::style(const std::string &style_name)
     882                 :                : {
     883      [ +  +  + ]:              3 :     style(workbook().style(style_name));
     884                 :              1 : }
     885                 :                : 
     886                 :              7 : style cell::style()
     887                 :                : {
     888   [ +  -  +  +  :              7 :     if (!has_format() || !format().has_style())
          +  +  +  -  +  
                +  -  - ]
     889                 :                :     {
     890            [ + ]:              1 :         throw invalid_attribute();
     891                 :                :     }
     892                 :                : 
     893            [ + ]:              6 :     auto f = format();
     894                 :                : 
     895            [ + ]:             12 :     return f.style();
     896                 :              6 : }
     897                 :                : 
     898                 :UBC           0 : const style cell::style() const
     899                 :                : {
     900   [ #  #  #  #  :              0 :     if (!has_format() || !format().has_style())
          #  #  #  #  #  
                #  #  # ]
     901                 :                :     {
     902            [ # ]:              0 :         throw invalid_attribute();
     903                 :                :     }
     904                 :                : 
     905         [ #  # ]:              0 :     return format().style();
     906                 :                : }
     907                 :                : 
     908                 :CBC           5 : bool cell::has_style() const
     909                 :                : {
     910   [ +  +  +  +  :              5 :     return has_format() && format().has_style();
          +  +  +  +  -  
                      - ]
     911                 :                : }
     912                 :                : 
     913                 :             11 : format cell::modifiable_format()
     914                 :                : {
     915         [ -  + ]:             11 :     if (!d_->format_.is_set())
     916                 :                :     {
     917            [ # ]:UBC           0 :         throw invalid_attribute();
     918                 :                :     }
     919                 :                : 
     920         [ +  + ]:CBC          11 :     return xlnt::format(d_->format_);
     921                 :                : }
     922                 :                : 
     923                 :            391 : const format cell::format() const
     924                 :                : {
     925         [ -  + ]:            391 :     if (!d_->format_.is_set())
     926                 :                :     {
     927            [ # ]:UBC           0 :         throw invalid_attribute();
     928                 :                :     }
     929                 :                : 
     930         [ +  + ]:CBC         391 :     return xlnt::format(d_->format_);
     931                 :                : }
     932                 :                : 
     933                 :              1 : alignment cell::alignment() const
     934                 :                : {
     935         [ +  + ]:              1 :     return format().alignment();
     936                 :                : }
     937                 :                : 
     938                 :              1 : border cell::border() const
     939                 :                : {
     940         [ +  + ]:              1 :     return format().border();
     941                 :                : }
     942                 :                : 
     943                 :              3 : fill cell::fill() const
     944                 :                : {
     945         [ +  + ]:              3 :     return format().fill();
     946                 :                : }
     947                 :                : 
     948                 :              7 : font cell::font() const
     949                 :                : {
     950         [ +  + ]:              7 :     return format().font();
     951                 :                : }
     952                 :                : 
     953                 :             17 : number_format cell::number_format() const
     954                 :                : {
     955         [ +  + ]:             17 :     return format().number_format();
     956                 :                : }
     957                 :                : 
     958                 :              1 : protection cell::protection() const
     959                 :                : {
     960         [ +  + ]:              1 :     return format().protection();
     961                 :                : }
     962                 :                : 
     963                 :            967 : bool cell::has_hyperlink() const
     964                 :                : {
     965                 :            967 :     return d_->hyperlink_.is_set();
     966                 :                : }
     967                 :                : 
     968                 :                : // comment
     969                 :                : 
     970                 :           1049 : bool cell::has_comment() const
     971                 :                : {
     972                 :           1049 :     return d_->comment_.is_set();
     973                 :                : }
     974                 :                : 
     975                 :              1 : void cell::clear_comment()
     976                 :                : {
     977         [ +  - ]:              1 :     if (has_comment())
     978                 :                :     {
     979      [ +  +  + ]:              1 :         d_->parent_->comments_.erase(reference().to_string());
     980                 :              1 :         d_->comment_.clear();
     981                 :                :     }
     982                 :              1 : }
     983                 :                : 
     984                 :             56 : class comment cell::comment() const
     985                 :                : {
     986         [ +  + ]:             56 :     if (!has_comment())
     987                 :                :     {
     988         [ +  + ]:              6 :         throw xlnt::exception("cell has no comment");
     989                 :                :     }
     990                 :                : 
     991                 :             54 :     return *d_->comment_.get();
     992                 :                : }
     993                 :                : 
     994                 :UBC           0 : void cell::comment(const std::string &text, const std::string &author)
     995                 :                : {
     996         [ #  # ]:              0 :     comment(xlnt::comment(text, author));
     997                 :              0 : }
     998                 :                : 
     999                 :CBC           4 : void cell::comment(const std::string &text, const class font &comment_font, const std::string &author)
    1000                 :                : {
    1001      [ +  +  + ]:              4 :     comment(xlnt::comment(xlnt::rich_text(text, comment_font), author));
    1002                 :              4 : }
    1003                 :                : 
    1004                 :             34 : void cell::comment(const class comment &new_comment)
    1005                 :                : {
    1006         [ -  + ]:             34 :     if (has_comment())
    1007                 :                :     {
    1008         [ #  # ]:UBC           0 :         *d_->comment_.get() = new_comment;
    1009                 :                :     }
    1010                 :                :     else
    1011                 :                :     {
    1012   [ +  +  +  + ]:CBC          34 :         d_->parent_->comments_[reference().to_string()] = new_comment;
    1013      [ +  +  + ]:             34 :         d_->comment_.set(&d_->parent_->comments_[reference().to_string()]);
    1014                 :                :     }
    1015                 :                : 
    1016                 :                :     // offset comment 5 pixels down and 5 pixels right of the top right corner of the cell
    1017            [ + ]:             34 :     auto cell_position = anchor();
    1018            [ + ]:             34 :     cell_position.first += static_cast<int>(width()) + 5;
    1019                 :             34 :     cell_position.second += 5;
    1020                 :                : 
    1021         [ +  + ]:             34 :     d_->comment_.get()->position(cell_position.first, cell_position.second);
    1022                 :                : 
    1023         [ +  + ]:             34 :     worksheet().register_comments_in_manifest();
    1024                 :             34 : }
    1025                 :                : 
    1026                 :             34 : double cell::width() const
    1027                 :                : {
    1028         [ +  + ]:             34 :     return worksheet().column_width(column());
    1029                 :                : }
    1030                 :                : 
    1031                 :UBC           0 : double cell::height() const
    1032                 :                : {
    1033         [ #  # ]:              0 :     return worksheet().row_height(row());
    1034                 :                : }
    1035                 :                : 
    1036                 :                : } // namespace xlnt
        

Generated by: LCOV version 2.3.1-beta