differential code coverage report with master
Current view: top level - source/workbook - workbook.cpp (source / functions) Coverage Total Hit UBC CBC
Current: coverage.info Lines: 76.8 % 996 765 231 765
Current Date: 2025-12-15 23:01:28 Functions: 83.1 % 189 157 32 157
Baseline: coverage_master.info Branches: 73.1 % 1079 789 580 1578
Baseline Date: 2025-12-15 23:01:27

             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 <fstream>
      28                 :                : #include <functional>
      29                 :                : 
      30                 :                : #include <xlnt/cell/cell.hpp>
      31                 :                : #include <xlnt/packaging/manifest.hpp>
      32                 :                : #include <xlnt/packaging/relationship.hpp>
      33                 :                : #include <xlnt/styles/alignment.hpp>
      34                 :                : #include <xlnt/styles/border.hpp>
      35                 :                : #include <xlnt/styles/fill.hpp>
      36                 :                : #include <xlnt/styles/font.hpp>
      37                 :                : #include <xlnt/styles/format.hpp>
      38                 :                : #include <xlnt/styles/number_format.hpp>
      39                 :                : #include <xlnt/styles/protection.hpp>
      40                 :                : #include <xlnt/styles/style.hpp>
      41                 :                : #include <xlnt/utils/exceptions.hpp>
      42                 :                : #include <xlnt/utils/path.hpp>
      43                 :                : #include <xlnt/utils/variant.hpp>
      44                 :                : #include <xlnt/workbook/metadata_property.hpp>
      45                 :                : #include <xlnt/workbook/named_range.hpp>
      46                 :                : #include <xlnt/workbook/theme.hpp>
      47                 :                : #include <xlnt/workbook/workbook.hpp>
      48                 :                : #include <xlnt/workbook/workbook_view.hpp>
      49                 :                : #include <xlnt/workbook/worksheet_iterator.hpp>
      50                 :                : #include <xlnt/worksheet/header_footer.hpp>
      51                 :                : #include <xlnt/worksheet/range.hpp>
      52                 :                : #include <xlnt/worksheet/worksheet.hpp>
      53                 :                : #include <detail/constants.hpp>
      54                 :                : #include <detail/default_case.hpp>
      55                 :                : #include <detail/implementations/cell_impl.hpp>
      56                 :                : #include <detail/implementations/workbook_impl.hpp>
      57                 :                : #include <detail/implementations/worksheet_impl.hpp>
      58                 :                : #include <detail/serialization/excel_thumbnail.hpp>
      59                 :                : #include <detail/serialization/open_stream.hpp>
      60                 :                : #include <detail/serialization/vector_streambuf.hpp>
      61                 :                : #include <detail/serialization/xlsx_consumer.hpp>
      62                 :                : #include <detail/serialization/xlsx_producer.hpp>
      63                 :                : 
      64                 :                : namespace {
      65                 :                : 
      66                 :                : using xlnt::detail::open_stream;
      67                 :                : 
      68                 :                : template <typename T>
      69                 :CBC          84 : std::vector<T> keys(const std::vector<std::pair<T, xlnt::variant>> &container)
      70                 :                : {
      71                 :             84 :     auto result = std::vector<T>();
      72                 :             84 :     auto iter = container.begin();
      73                 :                : 
      74         [ +  + ]:            663 :     while (iter != container.end())
      75                 :                :     {
      76            [ + ]:            579 :         result.push_back((iter++)->first);
      77                 :                :     }
      78                 :                : 
      79                 :             84 :     return result;
      80                 :UBC           0 : }
      81                 :                : 
      82                 :                : template <typename T>
      83                 :CBC         698 : bool contains(const std::vector<std::pair<T, xlnt::variant>> &container, const T key)
      84                 :                : {
      85         [ +  + ]:           3110 :     for (const auto &iter : container)
      86                 :                :     {
      87         [ +  + ]:           3106 :         if (iter.first == key)
      88                 :                :         {
      89                 :            694 :             return true;
      90                 :                :         }
      91                 :                :     }
      92                 :                : 
      93                 :              4 :     return false;
      94                 :                : }
      95                 :                : 
      96                 :           2660 : xlnt::path default_path(xlnt::relationship_type type, std::size_t index = 0)
      97                 :                : {
      98                 :                :     using xlnt::path;
      99                 :                :     using xlnt::relationship_type;
     100                 :                : 
     101   [ +  -  -  -  :           2660 :     switch (type)
          +  -  -  -  -  
          -  +  -  -  -  
          +  -  -  -  -  
          -  -  +  -  -  
          -  -  +  -  +  
          -  -  -  -  -  
                   -  - ]
     102                 :                :     {
     103                 :             10 :     case relationship_type::calculation_chain:
     104         [ +  + ]:             20 :         return path("/xl/calcChain.xml");
     105                 :UBC           0 :     case relationship_type::chartsheet:
     106         [ #  # ]:              0 :         return path("/xl/sheets/.xml");
     107                 :              0 :     case relationship_type::comments:
     108         [ #  # ]:              0 :         return path("/xl/comments.xml");
     109                 :              0 :     case relationship_type::connections:
     110         [ #  # ]:              0 :         return path("/xl/connections.xml");
     111                 :CBC         512 :     case relationship_type::core_properties:
     112         [ +  + ]:           1024 :         return path("/docProps/core.xml");
     113                 :UBC           0 :     case relationship_type::custom_properties:
     114         [ #  # ]:              0 :         return path("/docProps/custom.xml");
     115                 :              0 :     case relationship_type::custom_property:
     116         [ #  # ]:              0 :         return path("/xl/customProperty.xml");
     117                 :              0 :     case relationship_type::custom_xml_mappings:
     118         [ #  # ]:              0 :         return path("/xl/customXmlMappings.xml");
     119                 :              0 :     case relationship_type::dialogsheet:
     120         [ #  # ]:              0 :         return path("/xl/dialogsheets/sheet.xml");
     121                 :              0 :     case relationship_type::drawings:
     122         [ #  # ]:              0 :         return path("/xl/drawings/drawing.xml");
     123                 :CBC         512 :     case relationship_type::extended_properties:
     124         [ +  + ]:           1024 :         return path("/docProps/app.xml");
     125                 :UBC           0 :     case relationship_type::external_workbook_references:
     126         [ #  # ]:              0 :         return path("/xl/external.xml");
     127                 :              0 :     case relationship_type::hyperlink:
     128         [ #  # ]:              0 :         return path("/xl/hyperlink.xml");
     129                 :              0 :     case relationship_type::image:
     130         [ #  # ]:              0 :         return path("?");
     131                 :CBC         512 :     case relationship_type::office_document:
     132         [ +  + ]:           1024 :         return path("/xl/workbook.xml");
     133                 :UBC           0 :     case relationship_type::pivot_table:
     134         [ #  # ]:              0 :         return path("/xl/pivotTable.xml");
     135                 :              0 :     case relationship_type::pivot_table_cache_definition:
     136         [ #  # ]:              0 :         return path("?");
     137                 :              0 :     case relationship_type::pivot_table_cache_records:
     138         [ #  # ]:              0 :         return path("?");
     139                 :              0 :     case relationship_type::printer_settings:
     140         [ #  # ]:              0 :         return path("/xl/printerSettings.xml");
     141                 :              0 :     case relationship_type::query_table:
     142         [ #  # ]:              0 :         return path("/xl/queryTable.xml");
     143                 :              0 :     case relationship_type::revision_log:
     144         [ #  # ]:              0 :         return path("/xl/revisionLog.xml");
     145                 :CBC          90 :     case relationship_type::shared_string_table:
     146         [ +  + ]:            180 :         return path("/xl/sharedStrings.xml");
     147                 :UBC           0 :     case relationship_type::shared_workbook:
     148         [ #  # ]:              0 :         return path("/xl/sharedWorkbook.xml");
     149                 :              0 :     case relationship_type::shared_workbook_revision_headers:
     150         [ #  # ]:              0 :         return path("?");
     151                 :              0 :     case relationship_type::shared_workbook_user_data:
     152         [ #  # ]:              0 :         return path("?");
     153                 :              0 :     case relationship_type::single_cell_table_definitions:
     154         [ #  # ]:              0 :         return path("?");
     155                 :CBC         512 :     case relationship_type::stylesheet:
     156         [ +  + ]:           1024 :         return path("/xl/styles.xml");
     157                 :UBC           0 :     case relationship_type::table_definition:
     158         [ #  # ]:              0 :         return path("/xl/tableDefinition.xml");
     159                 :CBC         512 :     case relationship_type::theme:
     160         [ +  + ]:           1024 :         return path("/xl/theme/theme1.xml");
     161                 :UBC           0 :     case relationship_type::thumbnail:
     162         [ #  # ]:              0 :         return path("/docProps/thumbnail.jpg");
     163                 :              0 :     case relationship_type::unknown:
     164         [ #  # ]:              0 :         return path("/xl/unknown.xml");
     165                 :              0 :     case relationship_type::vml_drawing:
     166         [ #  # ]:              0 :         return path("/xl/vmlDrawing.xml");
     167                 :              0 :     case relationship_type::volatile_dependencies:
     168         [ #  # ]:              0 :         return path("/xl/volatileDependencies.xml");
     169                 :              0 :     case relationship_type::vbaproject:
     170         [ #  # ]:              0 :         return path("/xl/vbaProject.bin");
     171                 :              0 :     case relationship_type::worksheet:
     172   [ #  #  #  # ]:              0 :         return path("/xl/worksheets/sheet" + std::to_string(index) + ".xml");
     173                 :                :     }
     174                 :                : 
     175            [ # ]:              0 :     default_case(path("/xl/unknownPart.xml"));
     176                 :                : }
     177                 :                : 
     178                 :CBC        1330 : std::string content_type(xlnt::relationship_type type)
     179                 :                : {
     180                 :                :     using xlnt::relationship_type;
     181                 :                : 
     182   [ +  -  -  -  :           1330 :     switch (type)
          +  -  -  -  -  
          -  +  -  -  -  
          +  -  -  -  -  
          -  -  +  -  -  
          -  -  +  -  +  
          -  -  -  -  -  
                   -  - ]
     183                 :                :     {
     184                 :              5 :     case relationship_type::calculation_chain:
     185            [ + ]:             10 :         return "application/vnd.openxmlformats-officedocument.spreadsheetml.calcChain+xml";
     186                 :UBC           0 :     case relationship_type::chartsheet:
     187            [ # ]:              0 :         return "application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml";
     188                 :              0 :     case relationship_type::comments:
     189            [ # ]:              0 :         return "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml";
     190                 :              0 :     case relationship_type::connections:
     191            [ # ]:              0 :         return "application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml";
     192                 :CBC         256 :     case relationship_type::core_properties:
     193            [ + ]:            512 :         return "application/vnd.openxmlformats-package.core-properties+xml";
     194                 :UBC           0 :     case relationship_type::custom_properties:
     195            [ # ]:              0 :         return "application/vnd.openxmlformats-officedocument.custom-properties+xml";
     196                 :              0 :     case relationship_type::custom_property:
     197            [ # ]:              0 :         throw xlnt::unhandled_switch_case();
     198                 :              0 :     case relationship_type::custom_xml_mappings:
     199            [ # ]:              0 :         return "application/xml";
     200                 :              0 :     case relationship_type::dialogsheet:
     201            [ # ]:              0 :         return "application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml";
     202                 :              0 :     case relationship_type::drawings:
     203            [ # ]:              0 :         return "application/vnd.openxmlformats-officedocument.drawing+xml";
     204                 :CBC         256 :     case relationship_type::extended_properties:
     205            [ + ]:            512 :         return "application/vnd.openxmlformats-officedocument.extended-properties+xml";
     206                 :UBC           0 :     case relationship_type::external_workbook_references:
     207            [ # ]:              0 :         return "application/vnd.openxmlformats-officedocument.spreadsheetml.externalLink+xml";
     208                 :              0 :     case relationship_type::hyperlink:
     209            [ # ]:              0 :         throw xlnt::unhandled_switch_case();
     210                 :              0 :     case relationship_type::image:
     211            [ # ]:              0 :         throw xlnt::unhandled_switch_case();
     212                 :CBC         256 :     case relationship_type::office_document:
     213            [ + ]:            512 :         return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml";
     214                 :UBC           0 :     case relationship_type::pivot_table:
     215            [ # ]:              0 :         return "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml";
     216                 :              0 :     case relationship_type::pivot_table_cache_definition:
     217            [ # ]:              0 :         return "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml";
     218                 :              0 :     case relationship_type::pivot_table_cache_records:
     219            [ # ]:              0 :         return "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheRecords+xml";
     220                 :              0 :     case relationship_type::printer_settings:
     221            [ # ]:              0 :         return "application/vnd.openxmlformats-officedocument.spreadsheetml.printerSettings";
     222                 :              0 :     case relationship_type::query_table:
     223            [ # ]:              0 :         return "application/vnd.openxmlformats-officedocument.spreadsheetml.queryTable+xml";
     224                 :              0 :     case relationship_type::revision_log:
     225            [ # ]:              0 :         return "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionLog+xml";
     226                 :CBC          45 :     case relationship_type::shared_string_table:
     227            [ + ]:             90 :         return "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml";
     228                 :UBC           0 :     case relationship_type::shared_workbook:
     229            [ # ]:              0 :         throw xlnt::unhandled_switch_case();
     230                 :              0 :     case relationship_type::shared_workbook_revision_headers:
     231            [ # ]:              0 :         return "application/vnd.openxmlformats-officedocument.spreadsheetml.revisionHeaders+xml";
     232                 :              0 :     case relationship_type::shared_workbook_user_data:
     233            [ # ]:              0 :         return "application/vnd.openxmlformats-officedocument.spreadsheetml.userNames+xml";
     234                 :              0 :     case relationship_type::single_cell_table_definitions:
     235            [ # ]:              0 :         return "application/vnd.openxmlformats-officedocument.spreadsheetml.tableSingleCells+xml";
     236                 :CBC         256 :     case relationship_type::stylesheet:
     237            [ + ]:            512 :         return "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml";
     238                 :UBC           0 :     case relationship_type::table_definition:
     239            [ # ]:              0 :         return "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml";
     240                 :CBC         256 :     case relationship_type::theme:
     241            [ + ]:            512 :         return "application/vnd.openxmlformats-officedocument.theme+xml";
     242                 :UBC           0 :     case relationship_type::thumbnail:
     243            [ # ]:              0 :         return "image/jpeg";
     244                 :              0 :     case relationship_type::unknown:
     245            [ # ]:              0 :         return "";
     246                 :              0 :     case relationship_type::vml_drawing:
     247            [ # ]:              0 :         return "application/vnd.openxmlformats-officedocument.vmlDrawing";
     248                 :              0 :     case relationship_type::volatile_dependencies:
     249            [ # ]:              0 :         return "application/vnd.openxmlformats-officedocument.spreadsheetml.volatileDependencies+xml";
     250                 :              0 :     case relationship_type::vbaproject:
     251            [ # ]:              0 :         return "application/vnd.ms-office.vbaProject";
     252                 :              0 :     case relationship_type::worksheet:
     253            [ # ]:              0 :         return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml";
     254                 :                :     }
     255                 :                : 
     256            [ # ]:              0 :     default_case("application/xml");
     257                 :                : }
     258                 :                : 
     259                 :                : } // namespace
     260                 :                : 
     261                 :                : namespace xlnt {
     262                 :                : 
     263                 :              0 : bool workbook::has_core_property(xlnt::core_property type) const
     264                 :                : {
     265                 :              0 :     return ::contains(d_->core_properties_, type);
     266                 :                : }
     267                 :                : 
     268                 :CBC          41 : std::vector<xlnt::core_property> workbook::core_properties() const
     269                 :                : {
     270                 :             41 :     return keys(d_->core_properties_);
     271                 :                : }
     272                 :                : 
     273                 :            179 : variant workbook::core_property(xlnt::core_property type) const
     274                 :                : {
     275      [ +  +  - ]:            543 :     for (auto iter : d_->core_properties_)
     276                 :                :     {
     277         [ +  + ]:            543 :         if (iter.first == type)
     278                 :                :         {
     279            [ + ]:            358 :             return iter.second;
     280                 :                :         }
     281         [ +  + ]:            543 :     }
     282                 :                : 
     283         [ #  # ]:UBC           0 :     throw xlnt::exception("workbook doesn't have core property");
     284                 :                : }
     285                 :                : 
     286                 :CBC        1449 : void workbook::core_property(xlnt::core_property type, const variant &value)
     287                 :                : {
     288                 :           1449 :     register_package_part(relationship_type::core_properties);
     289                 :                : 
     290         [ +  + ]:           4042 :     for (auto &iter : d_->core_properties_)
     291                 :                :     {
     292         [ +  + ]:           2599 :         if (iter.first == type)
     293                 :                :         {
     294            [ + ]:              6 :             iter.second = value;
     295                 :              6 :             return;
     296                 :                :         }
     297                 :                :     }
     298                 :                : 
     299         [ +  + ]:           1443 :     d_->core_properties_.push_back({type, value});
     300                 :                : }
     301                 :                : 
     302                 :            697 : bool workbook::has_extended_property(xlnt::extended_property type) const
     303                 :                : {
     304                 :            697 :     return ::contains(d_->extended_properties_, type);
     305                 :                : }
     306                 :                : 
     307                 :             41 : std::vector<xlnt::extended_property> workbook::extended_properties() const
     308                 :                : {
     309                 :             41 :     return keys(d_->extended_properties_);
     310                 :                : }
     311                 :                : 
     312                 :           3939 : void workbook::extended_property(xlnt::extended_property type, const variant &value)
     313                 :                : {
     314                 :           3939 :     register_package_part(relationship_type::extended_properties);
     315                 :                : 
     316         [ +  + ]:          20977 :     for (auto &iter : d_->extended_properties_)
     317                 :                :     {
     318         [ +  + ]:          17692 :         if (iter.first == type)
     319                 :                :         {
     320            [ + ]:            654 :             iter.second = value;
     321                 :            654 :             return;
     322                 :                :         }
     323                 :                :     }
     324                 :                : 
     325         [ +  + ]:           3285 :     d_->extended_properties_.push_back({type, value});
     326                 :                : }
     327                 :                : 
     328                 :            398 : variant workbook::extended_property(xlnt::extended_property type) const
     329                 :                : {
     330      [ +  +  - ]:           2213 :     for (auto iter : d_->extended_properties_)
     331                 :                :     {
     332         [ +  + ]:           2213 :         if (iter.first == type)
     333                 :                :         {
     334            [ + ]:            796 :             return iter.second;
     335                 :                :         }
     336         [ +  + ]:           2213 :     }
     337                 :                : 
     338         [ #  # ]:UBC           0 :     throw xlnt::exception("workbook doesn't have extended property");
     339                 :                : }
     340                 :                : 
     341                 :CBC           1 : bool workbook::has_custom_property(const std::string &property_name) const
     342                 :                : {
     343            [ + ]:              1 :     return ::contains(d_->custom_properties_, property_name);
     344                 :                : }
     345                 :                : 
     346                 :              2 : std::vector<std::string> workbook::custom_properties() const
     347                 :                : {
     348                 :              2 :     return keys(d_->custom_properties_);
     349                 :                : }
     350                 :                : 
     351                 :              7 : void workbook::custom_property(const std::string &property_name, const variant &value)
     352                 :                : {
     353                 :              7 :     register_package_part(relationship_type::custom_properties);
     354                 :                : 
     355         [ +  + ]:              8 :     for (auto &iter : d_->custom_properties_)
     356                 :                :     {
     357         [ -  + ]:              1 :         if (iter.first == property_name)
     358                 :                :         {
     359            [ # ]:UBC           0 :             iter.second = value;
     360                 :              0 :             return;
     361                 :                :         }
     362                 :                :     }
     363                 :                : 
     364         [ +  + ]:CBC           7 :     d_->custom_properties_.push_back({property_name, value});
     365                 :                : }
     366                 :                : 
     367                 :              3 : variant workbook::custom_property(const std::string &property_name) const
     368                 :                : {
     369      [ +  +  - ]:              3 :     for (auto iter : d_->custom_properties_)
     370                 :                :     {
     371         [ +  - ]:              3 :         if (iter.first == property_name)
     372                 :                :         {
     373            [ + ]:              6 :             return iter.second;
     374                 :                :         }
     375         [ -  + ]:              3 :     }
     376                 :                : 
     377         [ #  # ]:UBC           0 :     throw xlnt::exception("workbook doesn't have custom property");
     378                 :                : }
     379                 :                : 
     380                 :              0 : void workbook::abs_path(const std::string &path)
     381                 :                : {
     382                 :              0 :     d_->abs_path_ = path;
     383                 :              0 : }
     384                 :                : 
     385                 :              0 : void workbook::arch_id_flags(const std::size_t flags)
     386                 :                : {
     387                 :              0 :     d_->arch_id_flags_ = flags;
     388                 :              0 : }
     389                 :                : 
     390                 :CBC         256 : workbook workbook::empty()
     391                 :                : {
     392         [ +  + ]:            256 :     workbook wb(std::make_shared<detail::workbook_impl>());
     393                 :                : 
     394            [ + ]:            256 :     wb.register_package_part(relationship_type::office_document);
     395                 :                : 
     396      [ +  +  + ]:           1024 :     wb.d_->manifest_.register_default_type("rels",
     397                 :                :         "application/vnd.openxmlformats-package.relationships+xml");
     398      [ +  +  + ]:           1280 :     wb.d_->manifest_.register_default_type("xml",
     399                 :                :         "application/xml");
     400                 :                : 
     401   [ +  +  +  + ]:            768 :     wb.thumbnail(excel_thumbnail(), "jpeg", "image/jpeg");
     402                 :                : 
     403         [ +  + ]:            256 :     wb.core_property(xlnt::core_property::creator, "Microsoft Office User");
     404         [ +  + ]:            256 :     wb.core_property(xlnt::core_property::last_modified_by, "Microsoft Office User");
     405      [ +  +  + ]:            256 :     wb.core_property(xlnt::core_property::created, datetime(2016, 8, 12, 3, 16, 56));
     406      [ +  +  + ]:            256 :     wb.core_property(xlnt::core_property::modified, datetime(2016, 8, 12, 3, 17, 16));
     407                 :                : 
     408         [ +  + ]:            256 :     wb.extended_property(xlnt::extended_property::application, "Microsoft Macintosh Excel");
     409         [ +  + ]:            256 :     wb.extended_property(xlnt::extended_property::doc_security, 0);
     410         [ +  + ]:            256 :     wb.extended_property(xlnt::extended_property::scale_crop, false);
     411   [ +  +  +  +  :           1024 :     wb.extended_property(xlnt::extended_property::heading_pairs, std::vector<variant>{variant("Worksheets"), variant(1)});
                +  -  - ]
     412         [ +  + ]:            256 :     wb.extended_property(xlnt::extended_property::titles_of_parts, {"Sheet1"});
     413         [ +  + ]:            256 :     wb.extended_property(xlnt::extended_property::company, "");
     414         [ +  + ]:            256 :     wb.extended_property(xlnt::extended_property::links_up_to_date, false);
     415         [ +  + ]:            256 :     wb.extended_property(xlnt::extended_property::shared_doc, false);
     416         [ +  + ]:            256 :     wb.extended_property(xlnt::extended_property::hyperlinks_changed, false);
     417         [ +  + ]:            256 :     wb.extended_property(xlnt::extended_property::app_version, "15.0300");
     418                 :                : 
     419                 :            256 :     detail::workbook_impl::file_version_t file_version;
     420            [ + ]:            256 :     file_version.app_name = "xl";
     421                 :            256 :     file_version.last_edited = 6;
     422                 :            256 :     file_version.lowest_edited = 6;
     423                 :            256 :     file_version.rup_build = 26709;
     424            [ + ]:            256 :     wb.d_->file_version_ = file_version;
     425                 :                : 
     426                 :            256 :     xlnt::workbook_view wb_view;
     427                 :            256 :     wb_view.active_tab = 0;
     428                 :            256 :     wb_view.x_window = 0;
     429                 :            256 :     wb_view.y_window = 460;
     430                 :            256 :     wb_view.window_width = 28800;
     431                 :            256 :     wb_view.window_height = 17460;
     432                 :            256 :     wb_view.tab_ratio = 500;
     433                 :            256 :     wb.view(wb_view);
     434                 :                : 
     435            [ + ]:            256 :     auto ws = wb.create_sheet();
     436                 :                : 
     437            [ + ]:            256 :     page_margins margins;
     438            [ + ]:            256 :     margins.left(0.7);
     439            [ + ]:            256 :     margins.right(0.7);
     440            [ + ]:            256 :     margins.top(0.75);
     441            [ + ]:            256 :     margins.bottom(0.75);
     442            [ + ]:            256 :     margins.header(0.3);
     443            [ + ]:            256 :     margins.footer(0.3);
     444            [ + ]:            256 :     ws.page_margins(margins);
     445                 :                : 
     446                 :            256 :     sheet_view view;
     447            [ + ]:            256 :     ws.add_view(view);
     448                 :                : 
     449                 :            256 :     auto &format_properties = ws.d_->format_properties_;
     450                 :            256 :     format_properties.base_col_width = 10.0;
     451                 :            256 :     format_properties.default_row_height = 16.0;
     452                 :                : 
     453            [ + ]:            256 :     wb.theme(xlnt::theme());
     454                 :                : 
     455            [ + ]:            256 :     wb.d_->stylesheet_ = detail::stylesheet();
     456            [ + ]:            256 :     auto &stylesheet = wb.d_->stylesheet_.get();
     457                 :            256 :     stylesheet.parent = wb.d_;
     458                 :                : 
     459            [ + ]:            256 :     auto default_border = border()
     460            [ + ]:            512 :                               .side(border_side::bottom, border::border_property())
     461            [ + ]:            512 :                               .side(border_side::top, border::border_property())
     462            [ + ]:            512 :                               .side(border_side::start, border::border_property())
     463            [ + ]:            512 :                               .side(border_side::end, border::border_property())
     464            [ + ]:            256 :                               .side(border_side::diagonal, border::border_property());
     465         [ +  + ]:            256 :     wb.d_->stylesheet_.get().borders.push_back(default_border);
     466                 :                : 
     467            [ + ]:            512 :     auto default_fill = fill(pattern_fill()
     468         [ +  + ]:            256 :                                  .type(pattern_fill_type::none));
     469            [ + ]:            256 :     stylesheet.fills.push_back(default_fill);
     470            [ + ]:            512 :     auto gray125_fill = pattern_fill()
     471            [ + ]:            256 :                             .type(pattern_fill_type::gray125);
     472         [ +  + ]:            256 :     stylesheet.fills.push_back(gray125_fill);
     473                 :                : 
     474            [ + ]:            256 :     auto default_font = font()
     475         [ +  + ]:            512 :                             .name("Calibri")
     476            [ + ]:            256 :                             .size(12)
     477         [ +  + ]:            512 :                             .scheme("minor")
     478            [ + ]:            256 :                             .family(2)
     479   [ +  +  +  + ]:            256 :                             .color(theme_color(1));
     480            [ + ]:            256 :     stylesheet.fonts.push_back(default_font);
     481                 :                : 
     482            [ + ]:            256 :     wb.create_builtin_style(0)
     483            [ + ]:            256 :         .border(default_border)
     484            [ + ]:            512 :         .fill(default_fill)
     485            [ + ]:            512 :         .font(default_font)
     486         [ +  + ]:            256 :         .number_format(xlnt::number_format::general());
     487                 :                : 
     488            [ + ]:            256 :     auto format = wb.create_format()
     489            [ + ]:            512 :         .border(default_border)
     490            [ + ]:            512 :         .fill(default_fill)
     491            [ + ]:            512 :         .font(default_font)
     492         [ +  + ]:            512 :         .number_format(xlnt::number_format::general())
     493      [ +  +  + ]:            512 :         .style("Normal");
     494            [ + ]:            256 :     wb.default_format(format);
     495                 :                : 
     496                 :            256 :     xlnt::calculation_properties calc_props;
     497                 :            256 :     calc_props.calc_id = 150000;
     498                 :            256 :     calc_props.concurrent_calc = false;
     499                 :            256 :     wb.calculation_properties(calc_props);
     500                 :                : 
     501                 :            256 :     return wb;
     502   [ +  +  -  -  :            512 : }
                   -  - ]
     503                 :                : 
     504                 :            248 : workbook::workbook()
     505                 :                : {
     506            [ + ]:            248 :     auto wb_template = empty();
     507                 :            248 :     swap(wb_template);
     508                 :            248 : }
     509                 :                : 
     510                 :              3 : workbook::workbook(const xlnt::path &file)
     511                 :                : {
     512            [ + ]:              3 :     *this = empty();
     513            [ + ]:              3 :     load(file);
     514                 :              3 : }
     515                 :                : 
     516                 :                : template <typename T>
     517                 :              3 : void workbook::construct(const xlnt::path &file, const T &password)
     518                 :                : {
     519            [ + ]:              3 :     *this = empty();
     520                 :              3 :     load(file, password);
     521                 :              2 : }
     522                 :                : 
     523                 :              1 : workbook::workbook(const xlnt::path &file, const std::string &password)
     524                 :                : {
     525            [ - ]:              1 :     construct(file, password);
     526                 :              1 : }
     527                 :                : 
     528                 :                : #if XLNT_HAS_FEATURE(U8_STRING_VIEW)
     529                 :              2 : workbook::workbook(const xlnt::path &file, std::u8string_view password)
     530                 :                : {
     531            [ + ]:              2 :     construct(file, password);
     532                 :              2 : }
     533                 :                : #endif
     534                 :                : 
     535                 :              1 : workbook::workbook(std::istream &data)
     536                 :                : {
     537            [ + ]:              1 :     *this = empty();
     538            [ + ]:              1 :     load(data);
     539                 :              1 : }
     540                 :                : 
     541                 :                : template <typename T>
     542                 :              1 : void workbook::construct(std::istream &data, const T &password)
     543                 :                : {
     544            [ + ]:              1 :     *this = empty();
     545                 :              1 :     load(data, password);
     546                 :              1 : }
     547                 :                : 
     548                 :UBC           0 : workbook::workbook(std::istream &data, const std::string &password)
     549                 :                : {
     550            [ # ]:              0 :     construct(data, password);
     551                 :              0 : }
     552                 :                : 
     553                 :                : #if XLNT_HAS_FEATURE(U8_STRING_VIEW)
     554                 :CBC           1 : workbook::workbook(std::istream &data, std::u8string_view password)
     555                 :                : {
     556            [ + ]:              1 :     construct(data, password);
     557                 :              1 : }
     558                 :                : #endif
     559                 :                : 
     560                 :            257 : workbook::workbook(std::shared_ptr<detail::workbook_impl> impl)
     561                 :                : {
     562            [ + ]:            257 :     set_impl(std::move(impl));
     563                 :            257 : }
     564                 :                : 
     565                 :            847 : workbook::workbook(std::weak_ptr<detail::workbook_impl> impl)
     566                 :                : {
     567            [ + ]:            847 :     set_impl(impl.lock());
     568                 :            847 : }
     569                 :                : 
     570                 :           1104 : void workbook::set_impl(std::shared_ptr<detail::workbook_impl> impl)
     571                 :                : {
     572         [ -  + ]:           1104 :     if (impl == nullptr)
     573                 :                :     {
     574            [ # ]:UBC           0 :         throw xlnt::invalid_parameter("invalid workbook pointer");
     575                 :                :     }
     576                 :                : 
     577                 :CBC        1104 :     d_ = std::move(impl);
     578                 :           1104 : }
     579                 :                : 
     580                 :           5651 : void workbook::register_package_part(relationship_type type)
     581                 :                : {
     582   [ +  +  +  +  :          16953 :     if (!manifest().has_relationship(path("/"), type))
                      + ]
     583                 :                :     {
     584      [ +  +  + ]:            768 :         manifest().register_override_type(default_path(type), content_type(type));
     585      [ +  +  + ]:           1536 :         manifest().register_relationship(uri("/"), type,
     586   [ +  +  +  +  :           3072 :             uri(default_path(type).relative_to(path("/")).string()),
                   +  + ]
     587                 :                :             target_mode::internal);
     588                 :                :     }
     589                 :           5651 : }
     590                 :                : 
     591                 :           1661 : void workbook::register_workbook_part(relationship_type type)
     592                 :                : {
     593      [ +  +  + ]:           3322 :     auto wb_rel = manifest().relationship(path("/"), relationship_type::office_document);
     594   [ +  +  +  +  :           6644 :     auto wb_path = manifest().canonicalize({wb_rel});
                   -  - ]
     595                 :                : 
     596      [ +  +  + ]:           1661 :     if (!manifest().has_relationship(wb_path, type))
     597                 :                :     {
     598      [ +  +  + ]:            562 :         manifest().register_override_type(default_path(type), content_type(type));
     599      [ +  +  + ]:           1124 :         manifest().register_relationship(uri(wb_path.string()), type,
     600   [ +  +  +  +  :           2248 :             uri(default_path(type).relative_to(wb_path.resolve(path("/"))).string()),
                +  +  + ]
     601                 :                :             target_mode::internal);
     602                 :                :     }
     603   [ +  -  -  -  :           3322 : }
                      - ]
     604                 :                : 
     605                 :             34 : void workbook::register_worksheet_part(worksheet ws, relationship_type type)
     606                 :                : {
     607         [ +  + ]:            102 :     auto wb_rel = manifest().relationship(path("/"),
     608            [ + ]:             34 :         relationship_type::office_document);
     609                 :             34 :     auto ws_rel = manifest().relationship(wb_rel.target().path(),
     610   [ +  +  +  +  :             34 :         d_->sheet_title_rel_id_map_.at(ws.title()));
                      + ]
     611   [ +  +  +  +  :             34 :     path ws_path(ws_rel.source().path().parent().append(ws_rel.target().path()));
                   +  + ]
     612                 :                : 
     613         [ +  - ]:             34 :     if (type == relationship_type::comments)
     614                 :                :     {
     615      [ +  +  + ]:             34 :         if (!manifest().has_relationship(ws_path, relationship_type::vml_drawing))
     616                 :                :         {
     617                 :              3 :             std::size_t file_number = 1;
     618         [ +  + ]:              3 :             path filename("vmlDrawing1.vml");
     619                 :              3 :             bool filename_exists = true;
     620                 :                : 
     621         [ +  + ]:              7 :             while (filename_exists)
     622                 :                :             {
     623                 :              4 :                 filename_exists = false;
     624                 :                : 
     625                 :              4 :                 for (auto current_ws_rel :
     626   [ +  +  +  +  :             14 :                     manifest().relationships(wb_rel.target().path(), xlnt::relationship_type::worksheet))
                   +  + ]
     627                 :                :                 {
     628   [ +  +  +  +  :              6 :                     path current_ws_path(current_ws_rel.source().path().parent().append(current_ws_rel.target().path()));
                   +  + ]
     629      [ +  +  + ]:              6 :                     if (!manifest().has_relationship(current_ws_path, xlnt::relationship_type::vml_drawing)) continue;
     630                 :                : 
     631                 :              2 :                     for (auto current_ws_child_rel :
     632   [ +  +  +  + ]:              5 :                         manifest().relationships(current_ws_path, xlnt::relationship_type::vml_drawing))
     633                 :                :                     {
     634   [ +  +  +  +  :              4 :                         if (current_ws_child_rel.target().path() == path("../drawings").append(filename))
             +  +  +  + ]
     635                 :                :                         {
     636                 :              1 :                             filename_exists = true;
     637                 :              1 :                             break;
     638                 :                :                         }
     639         [ +  + ]:              3 :                     }
     640   [ +  +  +  + ]:             14 :                 }
     641                 :                : 
     642         [ +  + ]:              4 :                 if (filename_exists)
     643                 :                :                 {
     644                 :              1 :                     file_number++;
     645   [ +  +  +  + ]:              1 :                     filename = path("vmlDrawing" + std::to_string(file_number) + ".vml");
     646                 :                :                 }
     647                 :                :             }
     648                 :                : 
     649      [ +  +  + ]:             15 :             manifest().register_default_type("vml", "application/vnd.openxmlformats-officedocument.vmlDrawing");
     650                 :                : 
     651      [ +  +  + ]:              3 :             const path relative_path(path("../drawings").append(filename));
     652            [ + ]:              6 :             manifest().register_relationship(
     653   [ +  +  +  + ]:              6 :                 uri(ws_path.string()), relationship_type::vml_drawing, uri(relative_path.string()), target_mode::internal);
     654                 :              3 :         }
     655                 :                : 
     656      [ +  +  + ]:             34 :         if (!manifest().has_relationship(ws_path, relationship_type::comments))
     657                 :                :         {
     658                 :              3 :             std::size_t file_number = 1;
     659         [ +  + ]:              6 :             path filename("comments1.xml");
     660                 :                : 
     661                 :                :             while (true)
     662                 :                :             {
     663   [ +  +  +  +  :              4 :                 if (!manifest().has_override_type(constants::package_xl().append(filename))) break;
                      + ]
     664                 :                : 
     665                 :              1 :                 file_number++;
     666   [ +  +  +  + ]:              1 :                 filename = path("comments" + std::to_string(file_number) + ".xml");
     667                 :                :             }
     668                 :                : 
     669         [ +  + ]:              3 :             const path absolute_path(constants::package_xl().append(filename));
     670         [ +  + ]:              9 :             manifest().register_override_type(
     671                 :                :                 absolute_path, "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml");
     672                 :                : 
     673      [ +  +  + ]:              3 :             const path relative_path(path("..").append(filename));
     674            [ + ]:              6 :             manifest().register_relationship(
     675   [ +  +  +  + ]:              6 :                 uri(ws_path.string()), relationship_type::comments, uri(relative_path.string()), target_mode::internal);
     676                 :              3 :         }
     677                 :                :     }
     678                 :             34 : }
     679                 :                : 
     680                 :             55 : const worksheet workbook::sheet_by_title(const std::string &title) const
     681                 :                : {
     682         [ +  + ]:             69 :     for (auto &impl : d_->worksheets_)
     683                 :                :     {
     684         [ +  + ]:             68 :         if (impl.title_ == title)
     685                 :                :         {
     686            [ + ]:             54 :             return worksheet(&impl);
     687                 :                :         }
     688                 :                :     }
     689                 :                : 
     690            [ + ]:              1 :     throw key_not_found();
     691                 :                : }
     692                 :                : 
     693                 :             25 : worksheet workbook::sheet_by_title(const std::string &title)
     694                 :                : {
     695         [ +  + ]:             48 :     for (auto &impl : d_->worksheets_)
     696                 :                :     {
     697         [ +  + ]:             43 :         if (impl.title_ == title)
     698                 :                :         {
     699            [ + ]:             20 :             return worksheet(&impl);
     700                 :                :         }
     701                 :                :     }
     702                 :                : 
     703            [ + ]:              5 :     throw key_not_found();
     704                 :                : }
     705                 :                : 
     706                 :            322 : worksheet workbook::sheet_by_index(std::size_t index)
     707                 :                : {
     708         [ +  + ]:            322 :     if (index >= d_->worksheets_.size())
     709                 :                :     {
     710            [ + ]:              1 :         throw invalid_parameter();
     711                 :                :     }
     712                 :                : 
     713                 :            321 :     auto iter = d_->worksheets_.begin();
     714                 :                : 
     715         [ +  + ]:            427 :     for (std::size_t i = 0; i < index; ++i)
     716                 :                :     {
     717                 :            106 :         ++iter;
     718                 :                :     }
     719                 :                : 
     720            [ + ]:            642 :     return worksheet(&*iter);
     721                 :                : }
     722                 :                : 
     723                 :           1213 : const worksheet workbook::sheet_by_index(std::size_t index) const
     724                 :                : {
     725         [ +  + ]:           1213 :     if (index >= d_->worksheets_.size())
     726                 :                :     {
     727            [ + ]:              1 :         throw invalid_parameter();
     728                 :                :     }
     729                 :                : 
     730                 :           1212 :     auto iter = d_->worksheets_.begin();
     731                 :                : 
     732         [ +  + ]:           1625 :     for (std::size_t i = 0; i < index; ++i, ++iter)
     733                 :                :     {
     734                 :                :     }
     735                 :                : 
     736            [ + ]:           2424 :     return worksheet(&*iter);
     737                 :                : }
     738                 :                : 
     739                 :UBC           0 : worksheet workbook::sheet_by_id(std::size_t id)
     740                 :                : {
     741         [ #  # ]:              0 :     for (auto &impl : d_->worksheets_)
     742                 :                :     {
     743         [ #  # ]:              0 :         if (impl.id_ == id)
     744                 :                :         {
     745            [ # ]:              0 :             return worksheet(&impl);
     746                 :                :         }
     747                 :                :     }
     748                 :                : 
     749            [ # ]:              0 :     throw key_not_found();
     750                 :                : }
     751                 :                : 
     752                 :              0 : const worksheet workbook::sheet_by_id(std::size_t id) const
     753                 :                : {
     754         [ #  # ]:              0 :     for (auto &impl : d_->worksheets_)
     755                 :                :     {
     756         [ #  # ]:              0 :         if (impl.id_ == id)
     757                 :                :         {
     758            [ # ]:              0 :             return worksheet(&impl);
     759                 :                :         }
     760                 :                :     }
     761                 :                : 
     762            [ # ]:              0 :     throw key_not_found();
     763                 :                : }
     764                 :                : 
     765                 :CBC           1 : bool workbook::sheet_hidden_by_index(std::size_t index) const
     766                 :                : {
     767         [ -  + ]:              1 :     if (index >= d_->sheet_hidden_.size())
     768                 :                :     {
     769            [ # ]:UBC           0 :         throw invalid_parameter();
     770                 :                :     }
     771                 :                : 
     772            [ + ]:CBC           1 :     return d_->sheet_hidden_.at(index);
     773                 :                : }
     774                 :                : 
     775                 :            162 : worksheet workbook::active_sheet()
     776                 :                : {
     777         [ +  + ]:            162 :     return sheet_by_index(d_->active_sheet_index_.is_set() ? d_->active_sheet_index_.get() : 0);
     778                 :                : }
     779                 :              1 : void workbook::active_sheet(std::size_t index)
     780                 :                : {
     781                 :              1 :     d_->active_sheet_index_.set(index);
     782                 :              1 :     d_->view_.get().active_tab = index;
     783                 :              1 : }
     784                 :                : 
     785                 :             11 : bool workbook::has_named_range(const std::string &name) const
     786                 :                : {
     787   [ +  +  +  +  :             27 :     for (auto worksheet : *this)
                +  +  + ]
     788                 :                :     {
     789      [ +  +  + ]:             17 :         if (worksheet.has_named_range(name))
     790                 :                :         {
     791                 :              9 :             return true;
     792                 :                :         }
     793                 :                :     }
     794                 :              2 :     return false;
     795                 :                : }
     796                 :                : 
     797                 :            301 : worksheet workbook::create_sheet()
     798                 :                : {
     799            [ + ]:            301 :     std::string title = "Sheet1";
     800                 :            301 :     int index = 1;
     801                 :                : 
     802                 :                :     // make a unique sheet name. Sheet<1...n>
     803      [ +  +  + ]:            364 :     while (contains(title))
     804                 :                :     {
     805            [ + ]:             63 :         title = "Sheet" + std::to_string(++index);
     806                 :                :     }
     807                 :                :     // unique sheet id
     808                 :            301 :     size_t sheet_id = 1;
     809   [ +  +  +  +  :            368 :     for (const auto ws : *this)
                   +  + ]
     810                 :                :     {
     811         [ +  + ]:             67 :         sheet_id = std::max(sheet_id, ws.id() + 1);
     812                 :                :     }
     813         [ +  + ]:            301 :     d_->worksheets_.push_back(detail::worksheet_impl(this, sheet_id, title));
     814                 :                :     // unique sheet file name
     815      [ +  +  + ]:            602 :     auto workbook_rel = d_->manifest_.relationship(path("/"), relationship_type::office_document);
     816      [ +  +  + ]:            301 :     auto workbook_files = d_->manifest_.relationships(workbook_rel.target().path());
     817                 :            302 :     auto rel_vec_contains = [&workbook_files](const xlnt::path &new_file_id) {
     818            [ + ]:            604 :         return workbook_files.end() != std::find_if(workbook_files.begin(), workbook_files.end(), [&new_file_id](const xlnt::relationship &rel) {
     819                 :            161 :             return rel.target().path() == new_file_id;
     820                 :            604 :         });
     821                 :            301 :     };
     822                 :                : 
     823                 :            301 :     size_t file_id = sheet_id;
     824            [ + ]:            301 :     xlnt::path sheet_relative_path;
     825                 :                :     do
     826                 :                :     {
     827   [ +  +  +  +  :            302 :         sheet_relative_path = path("worksheets").append("sheet" + std::to_string(file_id++) + ".xml");
                   +  + ]
     828      [ +  +  + ]:            302 :     } while (rel_vec_contains(sheet_relative_path));
     829                 :                : 
     830         [ +  + ]:            301 :     uri relative_sheet_uri(sheet_relative_path.string());
     831   [ +  +  +  + ]:            301 :     auto absolute_sheet_path = path("/xl").append(relative_sheet_uri.path());
     832         [ +  + ]:            602 :     d_->manifest_.register_override_type(
     833                 :                :         absolute_sheet_path, "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml");
     834                 :            301 :     auto ws_rel = d_->manifest_.register_relationship(
     835         [ +  + ]:            301 :         workbook_rel.target(), relationship_type::worksheet, relative_sheet_uri, target_mode::internal);
     836         [ +  + ]:            301 :     d_->sheet_title_rel_id_map_[title] = ws_rel;
     837                 :                : 
     838            [ + ]:            301 :     update_sheet_properties();
     839            [ + ]:            301 :     reorder_relationships();
     840                 :                : 
     841            [ + ]:            602 :     return worksheet(&d_->worksheets_.back());
     842                 :            301 : }
     843                 :                : 
     844                 :              3 : worksheet workbook::copy_sheet(worksheet to_copy)
     845                 :                : {
     846      [ +  +  + ]:              3 :     if (to_copy.d_->parent_.lock() != d_) throw invalid_parameter();
     847                 :                : 
     848            [ + ]:              2 :     detail::worksheet_impl impl(*to_copy.d_);
     849            [ + ]:              2 :     auto new_sheet = create_sheet();
     850            [ + ]:              2 :     impl.title_ = new_sheet.title();
     851            [ + ]:              2 :     impl.id_ = new_sheet.id();
     852            [ + ]:              2 :     *new_sheet.d_ = impl;
     853                 :                : 
     854                 :              4 :     return new_sheet;
     855                 :              2 : }
     856                 :                : 
     857                 :              1 : worksheet workbook::copy_sheet(worksheet to_copy, std::size_t index)
     858                 :                : {
     859         [ +  + ]:              1 :     copy_sheet(to_copy);
     860                 :                : 
     861         [ +  - ]:              1 :     if (index != d_->worksheets_.size() - 1)
     862                 :                :     {
     863                 :              1 :         auto iter = d_->worksheets_.begin();
     864                 :                : 
     865         [ -  + ]:              1 :         for (std::size_t i = 0; i < index; ++i, ++iter)
     866                 :                :         {
     867                 :                :         }
     868                 :                : 
     869            [ + ]:              1 :         d_->worksheets_.insert(iter, d_->worksheets_.back());
     870                 :              1 :         d_->worksheets_.pop_back();
     871                 :                :     }
     872                 :                : 
     873                 :              1 :     return sheet_by_index(index);
     874                 :                : }
     875                 :                : 
     876                 :              6 : std::size_t workbook::index(worksheet ws) const
     877                 :                : {
     878      [ +  +  + ]:              6 :     auto match = std::find(begin(), end(), ws);
     879                 :                : 
     880   [ +  +  +  + ]:              6 :     if (match == end())
     881                 :                :     {
     882            [ + ]:              1 :         throw invalid_parameter();
     883                 :                :     }
     884                 :                : 
     885            [ + ]:             15 :     return static_cast<std::size_t>(std::distance(begin(), match));
     886                 :                : }
     887                 :                : 
     888                 :              5 : void workbook::move_sheet(worksheet worksheet, std::size_t newIndex)
     889                 :                : {
     890         [ +  + ]:              5 :     if(newIndex >= sheet_count())
     891            [ + ]:              1 :         throw invalid_parameter();
     892                 :                : 
     893                 :              4 :     auto sourcePosition = d_->worksheets_.end();
     894                 :              4 :     auto targetPosition = d_->worksheets_.begin();
     895                 :              4 :     size_t currentIndex = 0;
     896                 :              4 :     size_t sourceIndex  = sheet_count();
     897                 :                : 
     898         [ +  + ]:             28 :     for(auto iter = d_->worksheets_.begin(); iter != d_->worksheets_.end(); ++iter)
     899                 :                :     {
     900         [ +  + ]:             24 :         if(worksheet.d_ == (&*iter))
     901                 :                :         {
     902                 :              3 :             sourcePosition = iter;
     903                 :              3 :             sourceIndex    = currentIndex;
     904                 :                :         }
     905                 :                : 
     906         [ +  + ]:             24 :         if(currentIndex == newIndex)
     907                 :              4 :             targetPosition = iter;
     908                 :                : 
     909                 :             24 :         ++currentIndex;
     910                 :                :     }
     911                 :                : 
     912         [ +  + ]:              4 :     if(sourcePosition == d_->worksheets_.end())
     913            [ + ]:              1 :         throw invalid_parameter();
     914                 :                : 
     915         [ +  + ]:              3 :     if(sourceIndex < newIndex)
     916                 :              2 :         ++targetPosition;
     917                 :                : 
     918                 :              3 :     d_->worksheets_.splice(targetPosition, d_->worksheets_, sourcePosition);
     919                 :              3 : }
     920                 :                : 
     921                 :              7 : void workbook::create_named_range(const std::string &name, worksheet range_owner, const std::string &reference_string)
     922                 :                : {
     923      [ +  +  + ]:              7 :     create_named_range(name, range_owner, range_reference(reference_string));
     924                 :              6 : }
     925                 :                : 
     926                 :              7 : void workbook::create_named_range(const std::string &name, worksheet range_owner, const range_reference &reference)
     927                 :                : {
     928      [ +  +  + ]:              8 :     sheet_by_title(range_owner.title()).create_named_range(name, reference);
     929                 :              6 : }
     930                 :                : 
     931                 :              2 : void workbook::remove_named_range(const std::string &name)
     932                 :                : {
     933   [ +  +  +  +  :              8 :     for (auto ws : *this)
                +  +  + ]
     934                 :                :     {
     935      [ +  +  + ]:              4 :         if (ws.has_named_range(name))
     936                 :                :         {
     937            [ + ]:              1 :             ws.remove_named_range(name);
     938                 :              1 :             return;
     939                 :                :         }
     940                 :                :     }
     941                 :                : 
     942            [ + ]:              1 :     throw key_not_found();
     943                 :                : }
     944                 :                : 
     945                 :              2 : range workbook::named_range(const std::string &name)
     946                 :                : {
     947   [ +  +  +  +  :              8 :     for (auto ws : *this)
                +  +  + ]
     948                 :                :     {
     949      [ +  +  + ]:              4 :         if (ws.has_named_range(name))
     950                 :                :         {
     951            [ + ]:              1 :             return ws.named_range(name);
     952                 :                :         }
     953                 :                :     }
     954                 :                : 
     955            [ + ]:              1 :     throw key_not_found();
     956                 :                : }
     957                 :                : 
     958                 :             78 : void workbook::load(std::istream &stream)
     959                 :                : {
     960            [ + ]:             78 :     clear();
     961            [ + ]:             78 :     detail::xlsx_consumer consumer(*this);
     962                 :                : 
     963                 :                :     try
     964                 :                :     {
     965            [ + ]:             78 :         consumer.read(stream);
     966                 :                :     }
     967         [ -  + ]:              1 :     catch (xlnt::exception &e)
     968                 :                :     {
     969   [ +  +  -  + ]:              3 :         if (e.what() == std::string("xlnt::exception : encrypted xlsx, password required"))
     970                 :                :         {
     971            [ - ]:UBC           0 :             stream.seekg(0, std::ios::beg);
     972         [ -  - ]:              0 :             consumer.read(stream, "VelvetSweatshop");
     973                 :                :         }
     974                 :                :         else
     975                 :                :         {
     976                 :CBC           1 :             throw;
     977                 :                :         }
     978            [ - ]:              1 :     }
     979                 :             78 : }
     980                 :                : 
     981                 :             23 : void workbook::load(const std::vector<std::uint8_t> &data)
     982                 :                : {
     983         [ -  + ]:             23 :     if (data.size() < 22) // the shortest ZIP file is 22 bytes
     984                 :                :     {
     985         [ #  # ]:UBC           0 :         throw xlnt::exception("file is empty or malformed");
     986                 :                :     }
     987                 :                : 
     988            [ + ]:CBC          23 :     xlnt::detail::vector_istreambuf data_buffer(data);
     989            [ + ]:             23 :     std::istream data_stream(&data_buffer);
     990            [ + ]:             23 :     load(data_stream);
     991                 :             23 : }
     992                 :                : 
     993                 :                : template <typename T>
     994                 :             12 : void workbook::load_internal(const T &filename)
     995                 :                : {
     996         [ +  + ]:             12 :     return load(path(filename));
     997                 :                : }
     998                 :                : 
     999                 :                : template <typename T>
    1000                 :              2 : void workbook::load_internal(const T &filename, const T &password)
    1001                 :                : {
    1002         [ +  + ]:              2 :     return load(path(filename), password);
    1003                 :                : }
    1004                 :                : 
    1005                 :             11 : void workbook::load(const std::string &filename)
    1006                 :                : {
    1007                 :             11 :     return load_internal(filename);
    1008                 :                : }
    1009                 :                : 
    1010                 :             53 : void workbook::load(const path &filename)
    1011                 :                : {
    1012            [ + ]:             53 :     std::ifstream file_stream;
    1013         [ +  + ]:             53 :     open_stream(file_stream, filename.string());
    1014                 :                : 
    1015      [ +  -  + ]:             53 :     if (!file_stream.good())
    1016                 :                :     {
    1017      [ #  #  # ]:UBC           0 :         throw xlnt::exception("file not found " + filename.string());
    1018                 :                :     }
    1019                 :                : 
    1020            [ + ]:CBC          53 :     load(file_stream);
    1021                 :             53 : }
    1022                 :                : 
    1023                 :UBC           0 : void workbook::load(const std::string &filename, const std::string &password)
    1024                 :                : {
    1025                 :              0 :     return load_internal(filename, password);
    1026                 :                : }
    1027                 :                : 
    1028                 :                : template <typename T>
    1029                 :CBC          14 : void workbook::load_internal(const xlnt::path &filename, const T &password)
    1030                 :                : {
    1031            [ + ]:             14 :     std::ifstream file_stream;
    1032         [ +  + ]:             14 :     open_stream(file_stream, filename.string());
    1033                 :                : 
    1034      [ +  -  + ]:             14 :     if (!file_stream.good())
    1035                 :                :     {
    1036      [ #  #  # ]:UBC           0 :         throw xlnt::exception("file not found " + filename.string());
    1037                 :                :     }
    1038                 :                : 
    1039            [ + ]:CBC          23 :     return load(file_stream, password);
    1040                 :             14 : }
    1041                 :                : 
    1042                 :              8 : void workbook::load(const path &filename, const std::string &password)
    1043                 :                : {
    1044                 :              8 :     load_internal(filename, password);
    1045                 :              3 : }
    1046                 :                : 
    1047                 :                : #if XLNT_HAS_FEATURE(U8_STRING_VIEW)
    1048                 :              6 : void workbook::load(const xlnt::path &filename, std::u8string_view password)
    1049                 :                : {
    1050                 :              6 :     load_internal(filename, password);
    1051                 :              6 : }
    1052                 :                : #endif
    1053                 :                : 
    1054                 :                : template <typename T>
    1055                 :              5 : void workbook::load_internal(const std::vector<std::uint8_t> &data, const T &password)
    1056                 :                : {
    1057         [ -  + ]:              5 :     if (data.size() < 22) // the shortest ZIP file is 22 bytes
    1058                 :                :     {
    1059         [ #  # ]:UBC           0 :         throw xlnt::exception("file is empty or malformed");
    1060                 :                :     }
    1061                 :                : 
    1062            [ + ]:CBC           5 :     xlnt::detail::vector_istreambuf data_buffer(data);
    1063            [ + ]:              5 :     std::istream data_stream(&data_buffer);
    1064            [ + ]:              5 :     load(data_stream, password);
    1065                 :              5 : }
    1066                 :                : 
    1067                 :              3 : void workbook::load(const std::vector<std::uint8_t> &data, const std::string &password)
    1068                 :                : {
    1069                 :              3 :     load_internal(data, password);
    1070                 :              3 : }
    1071                 :                : 
    1072                 :                : #if XLNT_HAS_FEATURE(U8_STRING_VIEW)
    1073                 :              2 : void workbook::load(const std::vector<std::uint8_t> &data, std::u8string_view password)
    1074                 :                : {
    1075                 :              2 :     load_internal(data, password);
    1076                 :              2 : }
    1077                 :                : #endif
    1078                 :                : 
    1079                 :                : template <typename T>
    1080                 :             21 : void workbook::load_internal(std::istream &stream, const T &password)
    1081                 :                : {
    1082            [ + ]:             21 :     clear();
    1083            [ + ]:             21 :     detail::xlsx_consumer consumer(*this);
    1084            [ + ]:             21 :     consumer.read(stream, password);
    1085                 :             21 : }
    1086                 :                : 
    1087                 :             11 : void workbook::load(std::istream &stream, const std::string &password)
    1088                 :                : {
    1089                 :             11 :     load_internal(stream, password);
    1090                 :              6 : }
    1091                 :                : 
    1092                 :                : #if XLNT_HAS_FEATURE(U8_STRING_VIEW)
    1093                 :             10 : void workbook::load(std::istream &stream, std::u8string_view password)
    1094                 :                : {
    1095                 :             10 :     load_internal(stream, password);
    1096                 :             10 : }
    1097                 :                : #endif
    1098                 :                : 
    1099                 :             13 : void workbook::save(std::vector<std::uint8_t> &data) const
    1100                 :                : {
    1101            [ + ]:             13 :     xlnt::detail::vector_ostreambuf data_buffer(data);
    1102            [ + ]:             13 :     std::ostream data_stream(&data_buffer);
    1103            [ + ]:             13 :     save(data_stream);
    1104                 :             13 : }
    1105                 :                : 
    1106                 :                : template <typename T>
    1107                 :UBC           0 : void workbook::save_internal(std::vector<std::uint8_t> &data, const T &password) const
    1108                 :                : {
    1109            [ # ]:              0 :     xlnt::detail::vector_ostreambuf data_buffer(data);
    1110            [ # ]:              0 :     std::ostream data_stream(&data_buffer);
    1111            [ # ]:              0 :     save(data_stream, password);
    1112                 :              0 : }
    1113                 :                : 
    1114                 :              0 : void workbook::save(std::vector<std::uint8_t> &data, const std::string &password) const
    1115                 :                : {
    1116                 :              0 :     save_internal(data, password);
    1117                 :              0 : }
    1118                 :                : 
    1119                 :                : #if XLNT_HAS_FEATURE(U8_STRING_VIEW)
    1120                 :              0 : void workbook::save(std::vector<std::uint8_t> &data, std::u8string_view password) const
    1121                 :                : {
    1122                 :              0 :     save_internal(data, password);
    1123                 :              0 : }
    1124                 :                : #endif
    1125                 :                : 
    1126                 :                : template <typename T>
    1127                 :CBC          26 : void workbook::save_internal(const T &filename) const
    1128                 :                : {
    1129         [ +  + ]:             26 :     save(path(filename));
    1130                 :             26 : }
    1131                 :                : 
    1132                 :                : template <typename T>
    1133                 :UBC           0 : void workbook::save_internal(const T &filename, const T &password) const
    1134                 :                : {
    1135         [ #  # ]:              0 :     save(path(filename), password);
    1136                 :              0 : }
    1137                 :                : 
    1138                 :CBC          25 : void workbook::save(const std::string &filename) const
    1139                 :                : {
    1140                 :             25 :     save_internal(filename);
    1141                 :             25 : }
    1142                 :                : 
    1143                 :UBC           0 : void workbook::save(const std::string &filename, const std::string &password) const
    1144                 :                : {
    1145                 :              0 :     save_internal(filename, password);
    1146                 :              0 : }
    1147                 :                : 
    1148                 :CBC          26 : void workbook::save(const path &filename) const
    1149                 :                : {
    1150            [ + ]:             26 :     std::ofstream file_stream;
    1151         [ +  + ]:             26 :     open_stream(file_stream, filename.string());
    1152            [ + ]:             26 :     save(file_stream);
    1153                 :             26 : }
    1154                 :                : 
    1155                 :                : template <typename T>
    1156                 :              4 : void workbook::save_internal(const xlnt::path &filename, const T &password) const
    1157                 :                : {
    1158            [ + ]:              4 :     std::ofstream file_stream;
    1159         [ +  + ]:              4 :     open_stream(file_stream, filename.string());
    1160            [ + ]:              4 :     save(file_stream, password);
    1161                 :              4 : }
    1162                 :                : 
    1163                 :              3 : void workbook::save(const path &filename, const std::string &password) const
    1164                 :                : {
    1165                 :              3 :     save_internal(filename, password);
    1166                 :              3 : }
    1167                 :                : 
    1168                 :                : #if XLNT_HAS_FEATURE(U8_STRING_VIEW)
    1169                 :              1 : void workbook::save(const xlnt::path &filename, std::u8string_view password) const
    1170                 :                : {
    1171                 :              1 :     save_internal(filename, password);
    1172                 :              1 : }
    1173                 :                : #endif
    1174                 :                : 
    1175                 :             39 : void workbook::save(std::ostream &stream) const
    1176                 :                : {
    1177            [ + ]:             39 :     detail::xlsx_producer producer(*this);
    1178            [ + ]:             39 :     producer.write(stream);
    1179                 :             39 : }
    1180                 :                : 
    1181                 :                : template <typename T>
    1182                 :              4 : void workbook::save_internal(std::ostream &stream, const T &password) const
    1183                 :                : {
    1184            [ + ]:              4 :     detail::xlsx_producer producer(*this);
    1185            [ + ]:              4 :     producer.write(stream, password);
    1186                 :              4 : }
    1187                 :                : 
    1188                 :              3 : void workbook::save(std::ostream &stream, const std::string &password) const
    1189                 :                : {
    1190                 :              3 :     save_internal(stream, password);
    1191                 :              3 : }
    1192                 :                : 
    1193                 :                : #if XLNT_HAS_FEATURE(U8_STRING_VIEW)
    1194                 :              1 : void workbook::save(std::ostream &stream, std::u8string_view password) const
    1195                 :                : {
    1196                 :              1 :     save_internal(stream, password);
    1197                 :              1 : }
    1198                 :                : #endif
    1199                 :                : 
    1200                 :                : #ifdef _MSC_VER
    1201                 :                : void workbook::save(const std::wstring &filename) const
    1202                 :                : {
    1203                 :                :     std::ofstream file_stream;
    1204                 :                :     open_stream(file_stream, filename);
    1205                 :                :     save(file_stream);
    1206                 :                : }
    1207                 :                : 
    1208                 :                : void workbook::save(const std::wstring &filename, const std::string &password) const
    1209                 :                : {
    1210                 :                :     std::ofstream file_stream;
    1211                 :                :     open_stream(file_stream, filename);
    1212                 :                :     save(file_stream, password);
    1213                 :                : }
    1214                 :                : 
    1215                 :                : void workbook::load(const std::wstring &filename)
    1216                 :                : {
    1217                 :                :     std::ifstream file_stream;
    1218                 :                :     open_stream(file_stream, filename);
    1219                 :                :     load(file_stream);
    1220                 :                : }
    1221                 :                : 
    1222                 :                : void workbook::load(const std::wstring &filename, const std::string &password)
    1223                 :                : {
    1224                 :                :     std::ifstream file_stream;
    1225                 :                :     open_stream(file_stream, filename);
    1226                 :                :     load(file_stream, password);
    1227                 :                : }
    1228                 :                : #endif
    1229                 :                : 
    1230                 :                : #if XLNT_HAS_FEATURE(U8_STRING_VIEW)
    1231                 :              1 : void workbook::save(std::u8string_view filename) const
    1232                 :                : {
    1233                 :              1 :     save_internal(filename);
    1234                 :              1 : }
    1235                 :                : 
    1236                 :UBC           0 : void workbook::save(std::u8string_view filename, std::u8string_view password) const
    1237                 :                : {
    1238                 :              0 :     save_internal(filename, password);
    1239                 :              0 : }
    1240                 :                : 
    1241                 :CBC           1 : void workbook::load(std::u8string_view filename)
    1242                 :                : {
    1243                 :              1 :     load_internal(filename);
    1244                 :              1 : }
    1245                 :                : 
    1246                 :              2 : void workbook::load(std::u8string_view filename, std::u8string_view password)
    1247                 :                : {
    1248                 :              2 :     load_internal(filename, password);
    1249                 :              2 : }
    1250                 :                : #endif
    1251                 :                : 
    1252                 :              8 : void workbook::remove_sheet(worksheet ws)
    1253                 :                : {
    1254            [ + ]:              8 :     auto match_iter = std::find_if(d_->worksheets_.begin(), d_->worksheets_.end(),
    1255            [ + ]:             23 :         [=](detail::worksheet_impl &comp) { return &comp == ws.d_; });
    1256                 :                : 
    1257         [ -  + ]:              8 :     if (match_iter == d_->worksheets_.end())
    1258                 :                :     {
    1259            [ # ]:UBC           0 :         throw invalid_parameter();
    1260                 :                :     }
    1261                 :                : 
    1262      [ +  +  + ]:CBC           8 :     auto ws_rel_id = d_->sheet_title_rel_id_map_.at(ws.title());
    1263      [ +  +  + ]:             16 :     auto wb_rel = d_->manifest_.relationship(path("/"), xlnt::relationship_type::office_document);
    1264      [ +  +  + ]:              8 :     auto ws_rel = d_->manifest_.relationship(wb_rel.target().path(), ws_rel_id);
    1265   [ +  +  +  +  :             56 :     auto ws_part = d_->manifest_.canonicalize({wb_rel, ws_rel}).resolve(path("/"));
             +  +  +  -  
                      - ]
    1266            [ + ]:              8 :     d_->manifest_.unregister_override_type(ws_part);
    1267         [ +  + ]:              8 :     auto rel_id_map = d_->manifest_.unregister_relationship(wb_rel.target(), ws_rel_id);
    1268         [ +  + ]:              8 :     d_->sheet_title_rel_id_map_.erase(ws.title());
    1269                 :              8 :     d_->worksheets_.erase(match_iter);
    1270                 :                : 
    1271                 :                :     // Shift sheet title->ID mappings down as a result of manifest::unregister_relationship above.
    1272         [ +  + ]:             32 :     for (auto &title_rel_id_pair : d_->sheet_title_rel_id_map_)
    1273                 :                :     {
    1274            [ + ]:             24 :         title_rel_id_pair.second = rel_id_map.count(title_rel_id_pair.second) > 0
    1275            [ + ]:             19 :             ? rel_id_map[title_rel_id_pair.second]
    1276      [ +  +  + ]:             43 :             : title_rel_id_pair.second;
    1277                 :                :     }
    1278                 :                : 
    1279            [ + ]:              8 :     update_sheet_properties();
    1280   [ +  +  -  -  :             16 : }
                   -  - ]
    1281                 :                : 
    1282                 :              1 : worksheet workbook::create_sheet(std::size_t index)
    1283                 :                : {
    1284            [ + ]:              1 :     create_sheet();
    1285                 :                : 
    1286         [ -  + ]:              1 :     if (index != d_->worksheets_.size() - 1)
    1287                 :                :     {
    1288                 :UBC           0 :         auto iter = d_->worksheets_.begin();
    1289                 :                : 
    1290         [ #  # ]:              0 :         for (std::size_t i = 0; i < index; ++i, ++iter)
    1291                 :                :         {
    1292                 :                :         }
    1293                 :                : 
    1294            [ # ]:              0 :         d_->worksheets_.insert(iter, d_->worksheets_.back());
    1295                 :              0 :         d_->worksheets_.pop_back();
    1296                 :                :     }
    1297                 :                : 
    1298                 :CBC           1 :     return sheet_by_index(index);
    1299                 :                : }
    1300                 :                : 
    1301                 :UBC           0 : worksheet workbook::create_sheet_with_rel(const std::string &title, const relationship &rel)
    1302                 :                : {
    1303                 :              0 :     auto sheet_id = d_->worksheets_.size() + 1;
    1304         [ #  # ]:              0 :     d_->worksheets_.push_back(detail::worksheet_impl(this, sheet_id, title));
    1305                 :                : 
    1306      [ #  #  # ]:              0 :     auto workbook_rel = d_->manifest_.relationship(path("/"), relationship_type::office_document);
    1307   [ #  #  #  #  :              0 :     auto sheet_absoulute_path = workbook_rel.target().path().parent().append(rel.target().path());
                   #  # ]
    1308         [ #  # ]:              0 :     d_->manifest_.register_override_type(sheet_absoulute_path,
    1309                 :                :         "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml");
    1310                 :              0 :     auto ws_rel = d_->manifest_.register_relationship(workbook_rel.target(),
    1311      [ #  #  # ]:              0 :         relationship_type::worksheet, rel.target(), target_mode::internal);
    1312         [ #  # ]:              0 :     d_->sheet_title_rel_id_map_[title] = ws_rel;
    1313                 :                : 
    1314            [ # ]:              0 :     update_sheet_properties();
    1315                 :                : 
    1316            [ # ]:              0 :     return worksheet(&d_->worksheets_.back());
    1317                 :              0 : }
    1318                 :                : 
    1319                 :CBC         337 : workbook::iterator workbook::begin()
    1320                 :                : {
    1321            [ + ]:            337 :     return iterator(*this, 0);
    1322                 :                : }
    1323                 :                : 
    1324                 :            330 : workbook::iterator workbook::end()
    1325                 :                : {
    1326            [ + ]:            330 :     return iterator(*this, d_->worksheets_.size());
    1327                 :                : }
    1328                 :                : 
    1329                 :           1191 : workbook::const_iterator workbook::begin() const
    1330                 :                : {
    1331                 :           1191 :     return cbegin();
    1332                 :                : }
    1333                 :                : 
    1334                 :           1192 : workbook::const_iterator workbook::end() const
    1335                 :                : {
    1336                 :           1192 :     return cend();
    1337                 :                : }
    1338                 :                : 
    1339                 :           1201 : workbook::const_iterator workbook::cbegin() const
    1340                 :                : {
    1341            [ + ]:           1201 :     return const_iterator(*this, 0);
    1342                 :                : }
    1343                 :                : 
    1344                 :           1193 : workbook::const_iterator workbook::cend() const
    1345                 :                : {
    1346            [ + ]:           1193 :     return const_iterator(*this, d_->worksheets_.size());
    1347                 :                : }
    1348                 :                : 
    1349                 :            639 : std::vector<std::string> workbook::sheet_titles() const
    1350                 :                : {
    1351                 :            639 :     std::vector<std::string> names;
    1352                 :                : 
    1353   [ +  +  +  +  :           1446 :     for (auto ws : *this)
                   +  + ]
    1354                 :                :     {
    1355      [ +  +  + ]:            807 :         names.push_back(ws.title());
    1356                 :                :     }
    1357                 :                : 
    1358                 :            639 :     return names;
    1359                 :UBC           0 : }
    1360                 :                : 
    1361                 :CBC         347 : std::size_t workbook::sheet_count() const
    1362                 :                : {
    1363                 :            347 :     return d_->worksheets_.size();
    1364                 :                : }
    1365                 :                : 
    1366                 :              2 : worksheet workbook::operator[](const std::string &name)
    1367                 :                : {
    1368                 :              2 :     return sheet_by_title(name);
    1369                 :                : }
    1370                 :                : 
    1371                 :            145 : worksheet workbook::operator[](std::size_t index)
    1372                 :                : {
    1373                 :            145 :     return sheet_by_index(index);
    1374                 :                : }
    1375                 :                : 
    1376                 :            197 : void workbook::clear()
    1377                 :                : {
    1378            [ + ]:            197 :     *d_ = detail::workbook_impl();
    1379                 :            197 :     d_->stylesheet_.clear();
    1380                 :            197 : }
    1381                 :                : 
    1382                 :             23 : bool workbook::compare(const workbook &other, bool compare_by_reference) const
    1383                 :                : {
    1384         [ +  + ]:             23 :     if (compare_by_reference)
    1385                 :                :     {
    1386                 :              9 :         return d_ == other.d_;
    1387                 :                :     }
    1388                 :                :     else
    1389                 :                :     {
    1390                 :             14 :         return *d_ == *other.d_;
    1391                 :                :     }
    1392                 :                : }
    1393                 :                : 
    1394                 :              7 : bool workbook::operator==(const workbook &rhs) const
    1395                 :                : {
    1396                 :              7 :     return compare(rhs, true);
    1397                 :                : }
    1398                 :                : 
    1399                 :              4 : bool workbook::operator!=(const workbook &rhs) const
    1400                 :                : {
    1401                 :              4 :     return !operator==(rhs);
    1402                 :                : }
    1403                 :                : 
    1404                 :            248 : void workbook::swap(workbook &right)
    1405                 :                : {
    1406                 :            248 :     std::swap(d_, right.d_);
    1407                 :            248 : }
    1408                 :                : 
    1409                 :              2 : workbook workbook::clone(clone_method method) const
    1410                 :                : {
    1411      [ +  +  - ]:              2 :     switch (method)
    1412                 :                :     {
    1413                 :              1 :     case clone_method::deep_copy:
    1414                 :                :     {
    1415         [ -  - ]:              1 :         workbook wb;
    1416            [ + ]:              1 :         *wb.d_ = *d_;
    1417                 :                : 
    1418   [ +  +  +  +  :              5 :         for (auto ws : wb)
                +  +  + ]
    1419                 :                :         {
    1420            [ + ]:              2 :             ws.parent(wb);
    1421                 :                :         }
    1422                 :                : 
    1423            [ + ]:              1 :         wb.d_->stylesheet_.get().parent = wb.d_;
    1424                 :                : 
    1425         [ -  + ]:              1 :         return wb;
    1426                 :UBC           0 :     }
    1427                 :CBC           1 :     case clone_method::shallow_copy:
    1428                 :                :     {
    1429            [ + ]:              1 :         return workbook(d_);
    1430                 :                :     }
    1431                 :UBC           0 :     default:
    1432            [ # ]:              0 :         throw xlnt::invalid_parameter("clone method not supported");
    1433                 :                :     }
    1434                 :                : }
    1435                 :                : 
    1436                 :CBC           1 : bool workbook::has_theme() const
    1437                 :                : {
    1438                 :              1 :     return d_->theme_.is_set();
    1439                 :                : }
    1440                 :                : 
    1441                 :UBC           0 : const theme &workbook::theme() const
    1442                 :                : {
    1443                 :              0 :     return d_->theme_.get();
    1444                 :                : }
    1445                 :                : 
    1446                 :CBC         328 : void workbook::theme(const class theme &value)
    1447                 :                : {
    1448                 :            328 :     d_->theme_ = value;
    1449                 :            328 :     register_workbook_part(relationship_type::theme);
    1450                 :            328 : }
    1451                 :                : 
    1452                 :             44 : std::vector<named_range> workbook::named_ranges() const
    1453                 :                : {
    1454                 :             44 :     std::vector<xlnt::named_range> named_ranges;
    1455                 :                : 
    1456   [ +  +  +  +  :            150 :     for (auto ws : *this)
                +  +  + ]
    1457                 :                :     {
    1458         [ -  + ]:             53 :         for (auto &ws_named_range : ws.d_->named_ranges_)
    1459                 :                :         {
    1460            [ # ]:UBC           0 :             named_ranges.push_back(ws_named_range.second);
    1461                 :                :         }
    1462                 :                :     }
    1463                 :                : 
    1464                 :CBC          44 :     return named_ranges;
    1465                 :UBC           0 : }
    1466                 :                : 
    1467                 :CBC         311 : format workbook::create_format(bool default_format)
    1468                 :                : {
    1469                 :            311 :     register_workbook_part(relationship_type::stylesheet);
    1470                 :            311 :     return d_->stylesheet_.get().create_format(default_format);
    1471                 :                : }
    1472                 :                : 
    1473                 :            256 : void workbook::default_format(const class format &format)
    1474                 :                : {
    1475                 :            256 :     d_->stylesheet_.get().default_format(format);
    1476                 :            256 : }
    1477                 :                : 
    1478                 :              2 : bool workbook::has_style(const std::string &name) const
    1479                 :                : {
    1480                 :              2 :     return d_->stylesheet_.get().has_style(name);
    1481                 :                : }
    1482                 :                : 
    1483                 :              1 : void workbook::clear_styles()
    1484                 :                : {
    1485            [ + ]:              2 :     apply_to_cells([](cell c) { c.clear_style(); });
    1486                 :              1 : }
    1487                 :                : 
    1488                 :              2 : void workbook::default_slicer_style(const std::string &value)
    1489                 :                : {
    1490                 :              2 :     d_->stylesheet_.get().default_slicer_style = value;
    1491                 :              2 : }
    1492                 :                : 
    1493                 :UBC           0 : std::string workbook::default_slicer_style() const
    1494                 :                : {
    1495                 :              0 :     return d_->stylesheet_.get().default_slicer_style.get();
    1496                 :                : }
    1497                 :                : 
    1498                 :CBC          48 : void workbook::enable_known_fonts()
    1499                 :                : {
    1500                 :             48 :     d_->stylesheet_.get().known_fonts_enabled = true;
    1501                 :             48 : }
    1502                 :                : 
    1503                 :UBC           0 : void workbook::disable_known_fonts()
    1504                 :                : {
    1505                 :              0 :     d_->stylesheet_.get().known_fonts_enabled = false;
    1506                 :              0 : }
    1507                 :                : 
    1508                 :              0 : bool workbook::known_fonts_enabled() const
    1509                 :                : {
    1510                 :              0 :     return d_->stylesheet_.get().known_fonts_enabled;
    1511                 :                : }
    1512                 :                : 
    1513                 :CBC           1 : void workbook::clear_formats()
    1514                 :                : {
    1515            [ + ]:              2 :     apply_to_cells([](cell c) { c.clear_format(); });
    1516                 :              1 : }
    1517                 :                : 
    1518                 :             13 : std::size_t workbook::format_count() const
    1519                 :                : {
    1520                 :             13 :     return d_->stylesheet_.get().format_impls.size();
    1521                 :                : }
    1522                 :                : 
    1523                 :              2 : void workbook::apply_to_cells(std::function<void(cell)> f)
    1524                 :                : {
    1525   [ +  +  +  +  :              6 :     for (auto ws : *this)
                +  +  + ]
    1526                 :                :     {
    1527   [ +  +  +  + ]:              4 :         for (auto row = ws.lowest_row(); row <= ws.highest_row(); ++row)
    1528                 :                :         {
    1529   [ +  +  +  +  :              6 :             for (auto column = ws.lowest_column(); column <= ws.highest_column(); ++column)
                   +  + ]
    1530                 :                :             {
    1531   [ +  +  +  - ]:              2 :                 if (ws.has_cell(cell_reference(column, row)))
    1532                 :                :                 {
    1533      [ +  +  + ]:              2 :                     f.operator()(ws.cell(cell_reference(column, row)));
    1534                 :                :                 }
    1535                 :                :             }
    1536                 :                :         }
    1537                 :                :     }
    1538                 :              2 : }
    1539                 :                : 
    1540                 :            884 : format workbook::format(std::size_t format_index)
    1541                 :                : {
    1542                 :            884 :     return d_->stylesheet_.get().format(format_index);
    1543                 :                : }
    1544                 :                : 
    1545                 :UBC           0 : const format workbook::format(std::size_t format_index) const
    1546                 :                : {
    1547                 :              0 :     return d_->stylesheet_.get().format(format_index);
    1548                 :                : }
    1549                 :                : 
    1550                 :CBC       17076 : manifest &workbook::manifest()
    1551                 :                : {
    1552                 :          17076 :     return d_->manifest_;
    1553                 :                : }
    1554                 :                : 
    1555                 :            804 : const manifest &workbook::manifest() const
    1556                 :                : {
    1557                 :            804 :     return d_->manifest_;
    1558                 :                : }
    1559                 :                : 
    1560                 :            189 : const rich_text &workbook::shared_strings(std::size_t index) const
    1561                 :                : {
    1562         [ +  - ]:            189 :     if (index < d_->shared_strings_values_.size())
    1563                 :                :     {
    1564                 :            189 :         return d_->shared_strings_values_.at(index);
    1565                 :                :     }
    1566                 :                : 
    1567   [ #  #  #  # ]:UBC           0 :     static rich_text empty;
    1568                 :              0 :     return empty;
    1569                 :                : }
    1570                 :                : 
    1571                 :              0 : std::vector<rich_text> &workbook::shared_strings()
    1572                 :                : {
    1573                 :              0 :     return d_->shared_strings_values_;
    1574                 :                : }
    1575                 :                : 
    1576                 :CBC          60 : const std::vector<rich_text> &workbook::shared_strings() const
    1577                 :                : {
    1578                 :             60 :     return d_->shared_strings_values_;
    1579                 :                : }
    1580                 :                : 
    1581                 :           1006 : std::size_t workbook::add_shared_string(const rich_text &shared, bool allow_duplicates)
    1582                 :                : {
    1583                 :           1006 :     register_workbook_part(relationship_type::shared_string_table);
    1584                 :                : 
    1585         [ +  + ]:           1006 :     if (!allow_duplicates)
    1586                 :                :     {
    1587            [ + ]:            292 :         auto it = d_->shared_strings_ids_.find(shared);
    1588                 :                : 
    1589         [ +  + ]:            292 :         if (it != d_->shared_strings_ids_.end())
    1590                 :                :         {
    1591                 :              4 :             return it->second;
    1592                 :                :         }
    1593                 :                :     }
    1594                 :                : 
    1595                 :           1002 :     auto sz = d_->shared_strings_ids_.size();
    1596                 :           1002 :     d_->shared_strings_ids_[shared] = sz;
    1597                 :           1002 :     d_->shared_strings_values_.push_back(shared);
    1598                 :                : 
    1599                 :           1002 :     return sz;
    1600                 :                : }
    1601                 :                : 
    1602                 :            366 : bool workbook::contains(const std::string &sheet_title) const
    1603                 :                : {
    1604   [ +  +  +  +  :            564 :     for (auto ws : *this)
                +  +  + ]
    1605                 :                :     {
    1606      [ +  +  + ]:            163 :         if (ws.title() == sheet_title) return true;
    1607                 :                :     }
    1608                 :                : 
    1609                 :            302 :     return false;
    1610                 :                : }
    1611                 :                : 
    1612                 :            256 : void workbook::thumbnail(const std::vector<std::uint8_t> &thumbnail,
    1613                 :                :     const std::string &extension, const std::string &content_type)
    1614                 :                : {
    1615   [ +  +  +  +  :            768 :     if (!d_->manifest_.has_relationship(path("/"), relationship_type::thumbnail))
                      - ]
    1616                 :                :     {
    1617            [ + ]:            256 :         d_->manifest_.register_default_type(extension, content_type);
    1618      [ +  +  + ]:            512 :         d_->manifest_.register_relationship(uri("/"), relationship_type::thumbnail,
    1619         [ +  + ]:            768 :             uri("docProps/thumbnail.jpeg"), target_mode::internal);
    1620                 :                :     }
    1621                 :                : 
    1622      [ +  +  + ]:            512 :     auto thumbnail_rel = d_->manifest_.relationship(path("/"), relationship_type::thumbnail);
    1623   [ +  +  +  + ]:            256 :     d_->images_[thumbnail_rel.target().to_string()] = thumbnail;
    1624                 :            256 : }
    1625                 :                : 
    1626                 :UBC           0 : const std::vector<std::uint8_t> &workbook::thumbnail() const
    1627                 :                : {
    1628      [ #  #  # ]:              0 :     auto thumbnail_rel = d_->manifest_.relationship(path("/"), relationship_type::thumbnail);
    1629      [ #  #  # ]:              0 :     return d_->images_.at(thumbnail_rel.target().to_string());
    1630                 :              0 : }
    1631                 :                : 
    1632                 :              0 : const std::unordered_map<std::string, std::vector<std::uint8_t>> &workbook::binaries() const
    1633                 :                : {
    1634                 :              0 :     return d_->binaries_;
    1635                 :                : }
    1636                 :                : 
    1637                 :CBC           7 : style workbook::create_style(const std::string &name)
    1638                 :                : {
    1639                 :              7 :     return d_->stylesheet_.get().create_style(name);
    1640                 :                : }
    1641                 :                : 
    1642                 :            257 : style workbook::create_builtin_style(const std::size_t builtin_id)
    1643                 :                : {
    1644                 :            257 :     return d_->stylesheet_.get().create_builtin_style(builtin_id);
    1645                 :                : }
    1646                 :                : 
    1647                 :              3 : style workbook::style(const std::string &name)
    1648                 :                : {
    1649                 :              3 :     return d_->stylesheet_.get().style(name);
    1650                 :                : }
    1651                 :                : 
    1652                 :              1 : const style workbook::style(const std::string &name) const
    1653                 :                : {
    1654                 :              1 :     return d_->stylesheet_.get().style(name);
    1655                 :                : }
    1656                 :                : 
    1657                 :             57 : calendar workbook::base_date() const
    1658                 :                : {
    1659                 :             57 :     return d_->base_date_;
    1660                 :                : }
    1661                 :                : 
    1662                 :             96 : void workbook::base_date(calendar base_date)
    1663                 :                : {
    1664                 :             96 :     d_->base_date_ = base_date;
    1665                 :             96 : }
    1666                 :                : 
    1667                 :UBC           0 : bool workbook::has_title() const
    1668                 :                : {
    1669                 :              0 :     return d_->title_.is_set();
    1670                 :                : }
    1671                 :                : 
    1672                 :              0 : std::string workbook::title() const
    1673                 :                : {
    1674                 :              0 :     return d_->title_.get();
    1675                 :                : }
    1676                 :                : 
    1677                 :              0 : void workbook::title(const std::string &title)
    1678                 :                : {
    1679                 :              0 :     d_->title_ = title;
    1680                 :              0 : }
    1681                 :                : 
    1682                 :CBC         367 : detail::workbook_impl &workbook::impl()
    1683                 :                : {
    1684                 :            367 :     return *d_;
    1685                 :                : }
    1686                 :                : 
    1687                 :            146 : const detail::workbook_impl &workbook::impl() const
    1688                 :                : {
    1689                 :            146 :     return *d_;
    1690                 :                : }
    1691                 :                : 
    1692                 :             94 : bool workbook::has_view() const
    1693                 :                : {
    1694                 :             94 :     return d_->view_.is_set();
    1695                 :                : }
    1696                 :                : 
    1697                 :             90 : workbook_view workbook::view() const
    1698                 :                : {
    1699         [ -  + ]:             90 :     if (!d_->view_.is_set())
    1700                 :                :     {
    1701            [ # ]:UBC           0 :         throw invalid_attribute();
    1702                 :                :     }
    1703                 :                : 
    1704                 :CBC          90 :     return d_->view_.get();
    1705                 :                : }
    1706                 :                : 
    1707                 :            340 : void workbook::view(const workbook_view &view)
    1708                 :                : {
    1709                 :            340 :     d_->view_ = view;
    1710                 :            340 : }
    1711                 :                : 
    1712                 :             44 : bool workbook::has_code_name() const
    1713                 :                : {
    1714                 :             44 :     return d_->code_name_.is_set();
    1715                 :                : }
    1716                 :                : 
    1717                 :UBC           0 : std::string workbook::code_name() const
    1718                 :                : {
    1719         [ #  # ]:              0 :     if (has_code_name())
    1720                 :                :     {
    1721            [ # ]:              0 :         throw invalid_attribute();
    1722                 :                :     }
    1723                 :                : 
    1724                 :              0 :     return d_->code_name_.get();
    1725                 :                : }
    1726                 :                : 
    1727                 :              0 : void workbook::code_name(const std::string &code_name)
    1728                 :                : {
    1729                 :              0 :     d_->code_name_ = code_name;
    1730                 :              0 : }
    1731                 :                : 
    1732                 :CBC          44 : bool workbook::has_file_version() const
    1733                 :                : {
    1734                 :             44 :     return d_->file_version_.is_set();
    1735                 :                : }
    1736                 :                : 
    1737                 :             40 : std::string workbook::app_name() const
    1738                 :                : {
    1739                 :             40 :     return d_->file_version_.get().app_name;
    1740                 :                : }
    1741                 :                : 
    1742                 :             40 : std::size_t workbook::last_edited() const
    1743                 :                : {
    1744                 :             40 :     return d_->file_version_.get().last_edited;
    1745                 :                : }
    1746                 :                : 
    1747                 :             40 : std::size_t workbook::lowest_edited() const
    1748                 :                : {
    1749                 :             40 :     return d_->file_version_.get().lowest_edited;
    1750                 :                : }
    1751                 :                : 
    1752                 :             40 : std::size_t workbook::rup_build() const
    1753                 :                : {
    1754                 :             40 :     return d_->file_version_.get().rup_build;
    1755                 :                : }
    1756                 :                : 
    1757                 :             44 : bool workbook::has_calculation_properties() const
    1758                 :                : {
    1759                 :             44 :     return d_->calculation_properties_.is_set();
    1760                 :                : }
    1761                 :                : 
    1762                 :             82 : class calculation_properties workbook::calculation_properties() const
    1763                 :                : {
    1764                 :             82 :     return d_->calculation_properties_.get();
    1765                 :                : }
    1766                 :                : 
    1767                 :            338 : void workbook::calculation_properties(const class calculation_properties &props)
    1768                 :                : {
    1769                 :            338 :     d_->calculation_properties_ = props;
    1770                 :            338 : }
    1771                 :                : 
    1772                 :             18 : void workbook::garbage_collect_formulae()
    1773                 :                : {
    1774                 :             18 :     auto any_with_formula = false;
    1775                 :                : 
    1776   [ +  +  +  +  :             36 :     for (auto ws : *this)
                +  +  + ]
    1777                 :                :     {
    1778   [ +  +  +  +  :            104 :         for (auto row : ws.rows(true))
             +  +  +  + ]
    1779                 :                :         {
    1780   [ +  +  +  +  :            512 :             for (auto cell : row)
                +  +  + ]
    1781                 :                :             {
    1782      [ +  +  + ]:            426 :                 if (cell.has_formula())
    1783                 :                :                 {
    1784                 :            136 :                     any_with_formula = true;
    1785                 :                :                 }
    1786                 :                :             }
    1787                 :             18 :         }
    1788                 :                :     }
    1789                 :                : 
    1790         [ +  + ]:             18 :     if (any_with_formula) return;
    1791                 :                : 
    1792      [ +  +  + ]:              4 :     auto wb_rel = manifest().relationship(path("/"), relationship_type::office_document);
    1793                 :                : 
    1794   [ +  +  +  +  :              2 :     if (manifest().has_relationship(wb_rel.target().path(), relationship_type::calculation_chain))
                      - ]
    1795                 :                :     {
    1796      [ +  +  + ]:              2 :         auto calc_chain_rel = manifest().relationship(wb_rel.target().path(), relationship_type::calculation_chain);
    1797   [ +  +  +  +  :             10 :         auto calc_chain_part = manifest().canonicalize({wb_rel, calc_chain_rel});
                   -  - ]
    1798            [ + ]:              2 :         manifest().unregister_override_type(calc_chain_part);
    1799      [ +  +  + ]:              2 :         manifest().unregister_relationship(wb_rel.target(), calc_chain_rel.id());
    1800                 :              2 :     }
    1801   [ +  +  -  -  :              4 : }
                   -  - ]
    1802                 :                : 
    1803                 :            327 : void workbook::update_sheet_properties()
    1804                 :                : {
    1805         [ +  - ]:            327 :     if (has_extended_property(xlnt::extended_property::titles_of_parts))
    1806                 :                :     {
    1807      [ +  +  + ]:            327 :         extended_property(xlnt::extended_property::titles_of_parts, sheet_titles());
    1808                 :                :     }
    1809                 :                : 
    1810         [ +  - ]:            327 :     if (has_extended_property(xlnt::extended_property::heading_pairs))
    1811                 :                :     {
    1812         [ +  + ]:            327 :         extended_property(xlnt::extended_property::heading_pairs,
    1813   [ +  +  +  -  :           1635 :             std::vector<variant>{variant("Worksheets"), variant(static_cast<int>(sheet_count()))});
                      - ]
    1814                 :                :     }
    1815   [ +  +  -  -  :            654 : }
                   -  - ]
    1816                 :                : 
    1817                 :                : namespace {
    1818                 :                : // true if a sheet index is != worksheet relationship index
    1819                 :            301 : bool needs_reorder(const std::unordered_map<std::string, std::string> &title_to_rels,
    1820                 :                :     const std::vector<std::string> &titles,
    1821                 :                :     std::vector<std::string> &relation_ids)
    1822                 :                : {
    1823                 :            301 :     bool all_match = true;
    1824         [ +  + ]:            669 :     for (std::size_t title_index = 0; title_index < titles.size(); ++title_index)
    1825                 :                :     {
    1826            [ + ]:            368 :         const auto &rel = title_to_rels.at(titles[title_index]);
    1827            [ + ]:            368 :         relation_ids.push_back(rel);
    1828         [ +  + ]:            368 :         const auto expected_rel_id = "rId" + std::to_string(title_index + 1);
    1829         [ +  + ]:            368 :         if (rel != expected_rel_id)
    1830                 :                :         {
    1831                 :             46 :             all_match = false;
    1832                 :                :         }
    1833                 :            368 :     }
    1834                 :            301 :     return !all_match; // if all are as expected, reorder not required
    1835                 :                : };
    1836                 :                : 
    1837                 :                : struct rel_id_sorter
    1838                 :                : {
    1839                 :                :     // true if lhs < rhs
    1840                 :            300 :     bool operator()(const xlnt::relationship &lhs, const xlnt::relationship &rhs)
    1841                 :                :     {
    1842                 :                :         // format is rTd<decimal number 1..n>
    1843         [ -  + ]:            300 :         if (lhs.id().size() != rhs.id().size()) // a number with more digits will be larger
    1844                 :                :         {
    1845                 :UBC           0 :             return lhs.id().size() < rhs.id().size();
    1846                 :                :         }
    1847                 :CBC         300 :         return lhs.id() < rhs.id();
    1848                 :                :     }
    1849                 :                : };
    1850                 :                : } // namespace
    1851                 :                : 
    1852                 :            301 : void workbook::reorder_relationships()
    1853                 :                : {
    1854            [ + ]:            301 :     const auto titles = sheet_titles();
    1855                 :                :     // the relation ID corresponding to the title at the same index is copied into here
    1856                 :            301 :     std::vector<std::string> worksheet_rel_ids;
    1857            [ + ]:            301 :     worksheet_rel_ids.reserve(titles.size());
    1858      [ +  +  + ]:            301 :     if (!needs_reorder(d_->sheet_title_rel_id_map_, titles, worksheet_rel_ids))
    1859                 :                :     {
    1860                 :            256 :         return;
    1861                 :                :     }
    1862                 :                :     // copy of existing relations
    1863   [ +  +  +  +  :             90 :     const auto wb_rel_target = manifest().relationship(path("/"), relationship_type::office_document).target();
                      + ]
    1864         [ +  + ]:             45 :     auto rel_copy = manifest().relationships(wb_rel_target.path());
    1865            [ + ]:             45 :     std::sort(rel_copy.begin(), rel_copy.end(), rel_id_sorter{});
    1866                 :                :     // clear existing relations
    1867         [ +  + ]:            250 :     for (const auto &rel : rel_copy)
    1868                 :                :     {
    1869         [ +  + ]:            205 :         manifest().unregister_relationship(wb_rel_target, rel.id());
    1870                 :                :     }
    1871                 :                :     // create new relations
    1872                 :             45 :     std::size_t index = 0;
    1873         [ +  + ]:            205 :     auto new_id = [&index]() { return "rId" + std::to_string(++index); }; // ids start from 1
    1874                 :                :     // worksheets first
    1875         [ +  + ]:            157 :     while (index < worksheet_rel_ids.size())
    1876                 :                :     {
    1877            [ + ]:            112 :         auto rel_it = std::find_if(rel_copy.begin(), rel_copy.end(),
    1878                 :            308 :             [&](const relationship &rel) { return rel.id() == worksheet_rel_ids[index]; });
    1879                 :                : 
    1880            [ + ]:            112 :         std::string rel_id = new_id();
    1881         [ +  + ]:            112 :         d_->sheet_title_rel_id_map_.at(titles[index - 1]) = rel_id; // update title -> relation mapping
    1882            [ + ]:            224 :         manifest().register_relationship(relationship(rel_id, rel_it->type(),
    1883   [ +  +  +  +  :            112 :             rel_it->source(), rel_it->target(), rel_it->target_mode()));
                      + ]
    1884                 :            112 :     }
    1885                 :                :     // then all the other relations in the same order they started (just new indices)
    1886         [ +  + ]:            250 :     for (const auto &old_rel : rel_copy)
    1887                 :                :     {
    1888      [ +  +  + ]:            205 :         if (old_rel.type() == relationship_type::worksheet)
    1889                 :                :         {
    1890                 :            112 :             continue;
    1891                 :                :         }
    1892            [ + ]:            186 :         manifest().register_relationship(relationship(new_id(), old_rel.type(),
    1893   [ +  +  +  +  :             93 :             old_rel.source(), old_rel.target(), old_rel.target_mode()));
                   +  + ]
    1894                 :                :     }
    1895   [ +  +  +  + ]:            557 : }
    1896                 :                : 
    1897                 :                : } // namespace xlnt
        

Generated by: LCOV version 2.3.1-beta