Skip to content
This repository has been archived by the owner on May 26, 2022. It is now read-only.

Write formulas to XLSX files. #425

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

stevesweets
Copy link

Ref this issue: #424

I utterly understand that reading formulas is a pain. It should be noted that writing formulas to ODS is rather a pain, too, but the nature of xlsx actually makes it rather easy to write them.

This way, we can use the super-performant spout when we want to generate an xlsx file that needs to contain some excel formulas, and I don't think this lands outside of the goals of Spout.

I await your judgement!

New function, try to identify a formula string
Supporting *writing* formulas in XLSX files is truly trivial.
@boxcla
Copy link

boxcla commented May 25, 2017

Verified that @stevesweets has signed the CLA. Thanks for the pull request!

@stevesweets
Copy link
Author

This works for this, too:

#352

if (CellHelper::isNonEmptyString($cellValue)) {

if (CellHelper::isFormulaString($cellValue)) {
$cellXML .= '><f>'.substr($cellValue,1).'</f><v>0</v></c>'; // seriously, that's it.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect that the <v>0</v> is not going to work across all softwares. Which software did you use to test your changes?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, by setting the value to 0, reading back a spreadsheet with a formula won't work as Spout would return "0" for the cell value. Not ideal...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested on OSX, with excel 15 and numbers.

0 works because excel formulas are recalculated when an excel file is loaded.

You are correct that reading a formula will result in unexpected results, I had hoped the title of the PR was specific enough for this to be clear.

Thanks for coming back to me, glad to have been of any use at all.

Copy link

@SimZal SimZal Jun 3, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried it on Win10 and LibreOffice and it doesn't seem to work. It displays 0, like adrilo predicted. Using empty "<v></v>" seems to work for me.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stevesweets can you try the empty <v></v>?
There may always be some software that won't work but if the main ones work, we can consider merging this change.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi there, realise i left this a long time - i will try this.

S

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how is the code for .ods?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I try do the change on code for .ods
ODS/Internal/Worksheet.php

        if (CellHelper::isFormulaString($cellValue)) {
            $data .= ' table:formula="'.$cellValue.'" office:value-type="float" office:value="' . 0 . '" calcext:value-type="float">';
            $data .= '<text:p>' . 0 . '</text:p>';
            $data .= '</table:table-cell>';
        }else if (CellHelper::isNonEmptyString($cellValue)) {
            $data .= ' office:value-type="string" calcext:value-type="string">';
            $cellValueLines = explode("\n", $cellValue);
            foreach ($cellValueLines as $cellValueLine) {
                $data .= '<text:p>' . $this->stringsEscaper->escape($cellValueLine) . '</text:p>';
            }
            $data .= '</table:table-cell>';    
        } else if (CellHelper::isBoolean($cellValue)) {...}

too add the same change the CellHelper.php like .xlsx

 public static function isFormulaString($value)
    {
        return (strpos($value,'=') === 0);
    }

but now have this problem
not reconize the form in ods like excel. i neet to open document "make change at formule" and save to func
image
image

this is the code .fods

 <table:table-row table:style-name="ro1">
     <table:table-cell office:value-type="float" office:value="1" calcext:value-type="float">
      <text:p>1</text:p>
     </table:table-cell>
     <table:table-cell office:value-type="float" office:value="9" calcext:value-type="float">
      <text:p>9</text:p>
     </table:table-cell>
     <table:table-cell office:value-type="float" office:value="3" calcext:value-type="float">
      <text:p>3</text:p>
     </table:table-cell>
     <table:table-cell office:value-type="float" office:value="7" calcext:value-type="float">
      <text:p>7</text:p>
     </table:table-cell>
     <table:table-cell table:formula="of:=[.A1]+[.B1]+[.C1]+[.D1]" office:value-type="float" office:value="20" calcext:value-type="float">
      <text:p>20</text:p>
     </table:table-cell>
    </table:table-row>

if any can help me i give thanks

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, you can see that formulas don't work the same:

<table:table-cell table:formula="of:=[.A1]+[.B1]+[.C1]+[.D1]" office:value-type="float" office:value="20" calcext:value-type="float">
      <text:p>20</text:p>

This would indicate a formula: table:formula="of:=[.A1]+[.B1]+[.C1]+[.D1]", so your isFormulaString implementation is incorrect. Setting the value to 0 may not work in ODS. This is a trick in XLSX because softwares do recompute the value when you open the file, but for ODS maybe softwares use the given value directly. In this case, I don't have a good solution for you.

@adrilo
Copy link
Collaborator

adrilo commented May 29, 2017

Thanks @stevesweets !
Most likely, this won't be merged until v3 is released. v3 should make it easier to work with formulas. But I'll keep the PR open, as a reference for future implementation.

@barryvdh barryvdh mentioned this pull request Jan 29, 2019
@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@StefanoGroenland
Copy link

Will this PR ever get merged?

@Slamdunk
Copy link

Slamdunk commented Mar 2, 2022

Merged a variation in openspout/openspout#5

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants