77#include < odr/internal/abstract/document_element.hpp>
88#include < odr/internal/abstract/filesystem.hpp>
99#include < odr/internal/ooxml/spreadsheet/ooxml_spreadsheet_parser.hpp>
10- #include < odr/internal/util/string_util.hpp>
1110#include < odr/internal/util/xml_util.hpp>
1211
1312#include < utility>
@@ -16,7 +15,8 @@ namespace odr::internal::ooxml::spreadsheet {
1615
1716namespace {
1817std::unique_ptr<abstract::ElementAdapter>
19- create_element_adapter (const Document &document, ElementRegistry ®istry);
18+ create_element_adapter (const Document &document, ElementRegistry ®istry,
19+ StyleRegistry &style_registry);
2020}
2121
2222Document::Document (std::shared_ptr<abstract::ReadableFilesystem> files)
@@ -56,7 +56,8 @@ Document::Document(std::shared_ptr<abstract::ReadableFilesystem> files)
5656 m_root_element = parse_tree (m_element_registry, parse_context,
5757 workbook_xml.document_element ());
5858
59- m_element_adapter = create_element_adapter (*this , m_element_registry);
59+ m_element_adapter =
60+ create_element_adapter (*this , m_element_registry, m_style_registry);
6061}
6162
6263const ElementRegistry &Document::element_registry () const {
@@ -104,8 +105,10 @@ class ElementAdapter final : public abstract::ElementAdapter,
104105 public abstract::FrameAdapter,
105106 public abstract::ImageAdapter {
106107public:
107- ElementAdapter (const Document &document, ElementRegistry ®istry)
108- : m_document(&document), m_registry(®istry) {}
108+ ElementAdapter (const Document &document, ElementRegistry ®istry,
109+ StyleRegistry &style_registry)
110+ : m_document(&document), m_registry(®istry),
111+ m_style_registry (&style_registry) {}
109112
110113 [[nodiscard]] ElementType
111114 element_type (const ElementIdentifier element_id) const override {
@@ -313,33 +316,45 @@ class ElementAdapter final : public abstract::ElementAdapter,
313316
314317 [[nodiscard]] std::string
315318 sheet_name (const ElementIdentifier element_id) const override {
316- (void )element_id;
317- return {}; // TODO
319+ return get_node (element_id).attribute (" name" ).value ();
318320 }
319321 [[nodiscard]] TableDimensions
320322 sheet_dimensions (const ElementIdentifier element_id) const override {
321- (void )element_id;
322- return {}; // TODO
323+ if (const ElementRegistry::Sheet *element =
324+ m_registry->sheet_element (element_id);
325+ element != nullptr ) {
326+ return element->dimensions ;
327+ }
328+ return {};
323329 }
324330 [[nodiscard]] TableDimensions
325331 sheet_content (const ElementIdentifier element_id,
326332 const std::optional<TableDimensions> range) const override {
327- (void )element_id;
328333 (void )range;
329- return {} ; // TODO
334+ return sheet_dimensions (element_id) ; // TODO
330335 }
331336 [[nodiscard]] ElementIdentifier
332337 sheet_cell (const ElementIdentifier element_id, const std::uint32_t column,
333338 const std::uint32_t row) const override {
334- (void )element_id;
335- (void )column;
336- (void )row;
337- return {}; // TODO
339+ if (const ElementRegistry::Sheet *sheet_element =
340+ m_registry->sheet_element (element_id);
341+ sheet_element != nullptr ) {
342+ if (const ElementRegistry::Sheet::Cell *cell =
343+ sheet_element->cell (column, row);
344+ cell != nullptr ) {
345+ return cell->element_id ;
346+ }
347+ }
348+ return null_element_id;
338349 }
339350 [[nodiscard]] ElementIdentifier
340351 sheet_first_shape (const ElementIdentifier element_id) const override {
341- (void )element_id;
342- return {}; // TODO
352+ if (const ElementRegistry::Sheet *sheet_element =
353+ m_registry->sheet_element (element_id);
354+ sheet_element != nullptr ) {
355+ return sheet_element->first_shape_id ;
356+ }
357+ return null_element_id;
343358 }
344359 [[nodiscard]] TableStyle
345360 sheet_style (const ElementIdentifier element_id) const override {
@@ -349,46 +364,73 @@ class ElementAdapter final : public abstract::ElementAdapter,
349364 [[nodiscard]] TableColumnStyle
350365 sheet_column_style (const ElementIdentifier element_id,
351366 const std::uint32_t column) const override {
352- (void )element_id;
353- (void )column;
354- return {}; // TODO
367+ TableColumnStyle result;
368+ if (const ElementRegistry::Sheet *sheet_element =
369+ m_registry->sheet_element (element_id);
370+ sheet_element != nullptr ) {
371+ const pugi::xml_node column_node = sheet_element->column_node (column);
372+ if (const pugi::xml_attribute width = column_node.attribute (" width" )) {
373+ result.width = Measure (width.as_float (), DynamicUnit (" ch" ));
374+ }
375+ }
376+ return result;
355377 }
356378 [[nodiscard]] TableRowStyle
357379 sheet_row_style (const ElementIdentifier element_id,
358380 const std::uint32_t row) const override {
359- (void )element_id;
360- (void )row;
361- return {}; // TODO
381+ TableRowStyle result;
382+ if (const ElementRegistry::Sheet *sheet_element =
383+ m_registry->sheet_element (element_id);
384+ sheet_element != nullptr ) {
385+ const pugi::xml_node row_node = sheet_element->row_node (row);
386+ if (const pugi::xml_attribute height = row_node.attribute (" ht" )) {
387+ result.height = Measure (height.as_float (), DynamicUnit (" pt" ));
388+ }
389+ }
390+ return result;
362391 }
363392 [[nodiscard]] TableCellStyle
364393 sheet_cell_style (const ElementIdentifier element_id,
365394 const std::uint32_t column,
366395 const std::uint32_t row) const override {
367- (void )element_id;
368- (void )column;
369- (void )row;
370- return {}; // TODO
396+ TableCellStyle result;
397+ if (const ElementRegistry::Sheet *sheet_element =
398+ m_registry->sheet_element (element_id);
399+ sheet_element != nullptr ) {
400+ if (const pugi::xml_attribute style_attr =
401+ sheet_element->cell_node (column, row).attribute (" s" );
402+ style_attr) {
403+ const std::uint32_t style_id = style_attr.as_uint ();
404+ const ResolvedStyle style = m_style_registry->cell_style (style_id);
405+ result.override (style.table_cell_style );
406+ }
407+ }
408+ return result;
371409 }
372410
373411 [[nodiscard]] TablePosition
374412 sheet_cell_position (const ElementIdentifier element_id) const override {
375- (void )element_id;
376- return {}; // TODO
413+ if (const ElementRegistry::SheetCell *cell_element =
414+ m_registry->sheet_cell_element (element_id);
415+ cell_element != nullptr ) {
416+ return cell_element->position ;
417+ }
418+ return {};
377419 }
378420 [[nodiscard]] bool
379421 sheet_cell_is_covered (const ElementIdentifier element_id) const override {
380422 (void )element_id;
381- return {} ; // TODO
423+ return false ; // TODO
382424 }
383425 [[nodiscard]] TableDimensions
384426 sheet_cell_span (const ElementIdentifier element_id) const override {
385427 (void )element_id;
386- return {}; // TODO
428+ return {1 , 1 }; // TODO
387429 }
388430 [[nodiscard]] ValueType
389431 sheet_cell_value_type (const ElementIdentifier element_id) const override {
390432 (void )element_id;
391- return {} ; // TODO
433+ return ValueType::string ; // TODO
392434 }
393435
394436 [[nodiscard]] TextStyle
@@ -430,64 +472,9 @@ class ElementAdapter final : public abstract::ElementAdapter,
430472 }
431473 void text_set_content (const ElementIdentifier element_id,
432474 const std::string &text) const override {
433- ElementRegistry::Element *element = m_registry->element (element_id);
434- ElementRegistry::Text *text_element = m_registry->text_element (element_id);
435- if (element == nullptr || text_element == nullptr ) {
436- return ;
437- }
438-
439- const pugi::xml_node first = get_node (element_id);
440- const pugi::xml_node last = text_element->last ;
441-
442- pugi::xml_node parent = first.parent ();
443- const pugi::xml_node old_first = first;
444- const pugi::xml_node old_last = last;
445- pugi::xml_node new_first = old_first;
446- pugi::xml_node new_last = last;
447-
448- const auto insert_node = [&](const char *node) {
449- const pugi::xml_node new_node =
450- parent.insert_child_before (node, old_first);
451- if (new_first == old_first) {
452- new_first = new_node;
453- }
454- new_last = new_node;
455- return new_node;
456- };
457-
458- for (const util::xml::StringToken &token : util::xml::tokenize_text (text)) {
459- switch (token.type ) {
460- case util::xml::StringToken::Type::none:
461- break ;
462- case util::xml::StringToken::Type::string: {
463- auto text_node = insert_node (" w:t" );
464- text_node.append_child (pugi::xml_node_type::node_pcdata)
465- .text ()
466- .set (token.string .c_str ());
467- } break ;
468- case util::xml::StringToken::Type::spaces: {
469- auto text_node = insert_node (" w:t" );
470- text_node.append_attribute (" xml:space" ).set_value (" preserve" );
471- text_node.append_child (pugi::xml_node_type::node_pcdata)
472- .text ()
473- .set (token.string .c_str ());
474- } break ;
475- case util::xml::StringToken::Type::tabs: {
476- for (std::size_t i = 0 ; i < token.string .size (); ++i) {
477- insert_node (" w:tab" );
478- }
479- } break ;
480- }
481- }
482-
483- element->node = new_first;
484- text_element->last = new_last;
485-
486- for (pugi::xml_node node = old_first; node != old_last.next_sibling ();) {
487- const pugi::xml_node next = node.next_sibling ();
488- parent.remove_child (node);
489- node = next;
490- }
475+ (void )element_id;
476+ (void )text;
477+ // TODO
491478 }
492479 [[nodiscard]] TextStyle
493480 text_style (const ElementIdentifier element_id) const override {
@@ -502,37 +489,56 @@ class ElementAdapter final : public abstract::ElementAdapter,
502489
503490 [[nodiscard]] AnchorType
504491 frame_anchor_type (const ElementIdentifier element_id) const override {
505- const pugi::xml_node node = get_node (element_id);
506-
507- if (node.child (" wp:inline" )) {
508- return AnchorType::as_char;
509- }
510- return AnchorType::as_char; // TODO default?
492+ return AnchorType::at_page;
511493 }
512494 [[nodiscard]] std::optional<std::string>
513495 frame_x (const ElementIdentifier element_id) const override {
514- (void )element_id;
515- return std::nullopt ;
496+ if (const std::optional<Measure> x =
497+ read_emus_attribute (get_node (element_id)
498+ .child (" xdr:pic" )
499+ .child (" xdr:spPr" )
500+ .child (" a:xfrm" )
501+ .child (" a:off" )
502+ .attribute (" x" ))) {
503+ return x->to_string ();
504+ }
505+ return {};
516506 }
517507 [[nodiscard]] std::optional<std::string>
518508 frame_y (const ElementIdentifier element_id) const override {
519- (void )element_id;
520- return std::nullopt ;
509+ if (const std::optional<Measure> y =
510+ read_emus_attribute (get_node (element_id)
511+ .child (" xdr:pic" )
512+ .child (" xdr:spPr" )
513+ .child (" a:xfrm" )
514+ .child (" a:off" )
515+ .attribute (" y" ))) {
516+ return y->to_string ();
517+ }
518+ return {};
521519 }
522520 [[nodiscard]] std::optional<std::string>
523521 frame_width (const ElementIdentifier element_id) const override {
524- const pugi::xml_node inner_node = get_frame_inner_node (element_id);
525- if (const std::optional<Measure> width = read_emus_attribute (
526- inner_node.child (" wp:extent" ).attribute (" cx" ))) {
522+ if (const std::optional<Measure> width =
523+ read_emus_attribute (get_node (element_id)
524+ .child (" xdr:pic" )
525+ .child (" xdr:spPr" )
526+ .child (" a:xfrm" )
527+ .child (" a:ext" )
528+ .attribute (" cx" ))) {
527529 return width->to_string ();
528530 }
529531 return {};
530532 }
531533 [[nodiscard]] std::optional<std::string>
532534 frame_height (const ElementIdentifier element_id) const override {
533- const pugi::xml_node inner_node = get_frame_inner_node (element_id);
534- if (const std::optional<Measure> height = read_emus_attribute (
535- inner_node.child (" wp:extent" ).attribute (" cy" ))) {
535+ if (const std::optional<Measure> height =
536+ read_emus_attribute (get_node (element_id)
537+ .child (" xdr:pic" )
538+ .child (" xdr:spPr" )
539+ .child (" a:xfrm" )
540+ .child (" a:ext" )
541+ .attribute (" cy" ))) {
536542 return height->to_string ();
537543 }
538544 return {};
@@ -577,6 +583,7 @@ class ElementAdapter final : public abstract::ElementAdapter,
577583private:
578584 const Document *m_document{nullptr };
579585 ElementRegistry *m_registry{nullptr };
586+ StyleRegistry *m_style_registry{nullptr };
580587
581588 [[nodiscard]] pugi::xml_node
582589 get_node (const ElementIdentifier element_id) const {
@@ -588,42 +595,14 @@ class ElementAdapter final : public abstract::ElementAdapter,
588595 return {};
589596 }
590597
591- [[nodiscard]] pugi::xml_node
592- get_frame_inner_node (const ElementIdentifier element_id) const {
593- const pugi::xml_node node = get_node (element_id);
594- if (const pugi::xml_node anchor = node.child (" wp:anchor" )) {
595- return anchor;
596- }
597- if (const pugi::xml_node inline_node = node.child (" wp:inline" )) {
598- return inline_node;
599- }
600- return {};
601- }
602-
603598 [[nodiscard]] static std::string get_text (const pugi::xml_node node) {
604- const std::string name = node.name ();
605-
606- if (name == " w:t" ) {
599+ if (const std::string name = node.name (); name == " t" || name == " v" ) {
607600 return node.text ().get ();
608601 }
609- if (name == " w:tab" ) {
610- return " \t " ;
611- }
612602
613603 return " " ;
614604 }
615605
616- [[nodiscard]] const char *
617- get_style_name (const ElementIdentifier element_id) const {
618- const pugi::xml_node node = get_node (element_id);
619- for (pugi::xml_attribute attribute : node.attributes ()) {
620- if (util::string::ends_with (attribute.name (), " :style-name" )) {
621- return attribute.value ();
622- }
623- }
624- return {};
625- }
626-
627606 [[nodiscard]] ResolvedStyle
628607 get_partial_style (const ElementIdentifier element_id) const {
629608 if (const ElementType type = element_type (element_id);
@@ -655,8 +634,9 @@ class ElementAdapter final : public abstract::ElementAdapter,
655634};
656635
657636std::unique_ptr<abstract::ElementAdapter>
658- create_element_adapter (const Document &document, ElementRegistry ®istry) {
659- return std::make_unique<ElementAdapter>(document, registry);
637+ create_element_adapter (const Document &document, ElementRegistry ®istry,
638+ StyleRegistry &style_registry) {
639+ return std::make_unique<ElementAdapter>(document, registry, style_registry);
660640}
661641
662642} // namespace
0 commit comments