Skip to content

templateProcessor->setCheckbox: support Word 2007 checkboxes #2779

Open
@dmgruben

Description

@dmgruben

Describe the problem

Word 2007 uses <w:checkBox> instead of w14:checkBox and <w:ffData> instead of <w:sdt>:

<w:ffData>  
  <w:checkBox>  
    <w:size w:val="20" />  
    <w:checked w:val="true" />  
  </w:checkBox>  
</w:ffData>  

Describe the expected behavior

I wrote a method in a subclass that supports this:

/**
     * Extend setCheckbox so it allows for the <w:checkBox> and <w:checked> tag within <w::ffData>
     * @see https://learn.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.checkbox?view=openxml-3.0.1#remarks
     * @see https://learn.microsoft.com/en-us/dotnet/api/documentformat.openxml.wordprocessing.checked?view=openxml-3.0.1#remarks
     * @param  string  $search
     * @param  bool  $checked
     * @return void
     */
    public function setCheckbox(string $search, bool $checked): void
    {
        parent::setCheckbox($search, $checked);

        $search = parent::ensureMacroCompleted($search);
        $blockType = 'w:ffData';

        $where = $this->findContainingXmlBlockForMacro($search, $blockType);
        if (!is_array($where)) {
            return;
        }

        $checkbox_end_tag = '</w:checkBox>';
        $block = $this->getSlice($where['start'], $where['end']);

        // test if the block contains the <w:checkBox> tag
        if (!is_string($block) || !str_contains($block, $checkbox_end_tag)) {
            return;
        }

        $val = $checked ? 'true' : 'false';
        $block = preg_replace('@(<w:checked w:val=)".*?"(/>)@', '$1"'.$val.'"$2', $block, -1, $checked_replaced);

        // in case there is a <w:checked/> tag, then above does not match.
        // this shouldn't happen, but still, don't trust spreadsheet clients too much
        if (!$checked_replaced) {
            $checked_tag = '<w:checked w:val="'.$val.'" />';
            $block = preg_replace('@<w:checked[^>]*>@', $checked_tag, $block, -1, $checked_replaced);
        }

        // the <w:checked> tag is not always present and is being added on first change.
        if (!$checked_replaced) {
            // there is no checked tag yet, so we add it
            $block = str_replace($checkbox_end_tag, $checked_tag.$checkbox_end_tag, $block);
        }
        $this->replaceXmlBlock($search, $block, $blockType);
    }

Priority

  • I want to crowdfund the feature (with @algora-io) and fund a community developer.
  • I want to pay the feature and fund a maintainer for that. (Contact @Progi1984)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions