Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Any chance PhpSpreadsheet can support data bar in Conditional format? #938

Closed
fdreamsu opened this issue Mar 19, 2019 · 5 comments
Closed

Comments

@fdreamsu
Copy link

This is a feature request. Current conditional format functions can not build excel like this.
image
Anyone knows how to do it with PHP?

@MarkBaker
Copy link
Member

Looks like a sparkline to me, and no it isn't something that PHPSPreadsheet can do

@fdreamsu
Copy link
Author

Well, I unzip an excel file and figure out dataBar code myself. I finnaly did it with some ugly coding, maybe I will optimize them some other day.
PhpOffice\PhpSpreadsheet\Style\Conditional:15

class Conditional implements IComparable
{
    // Condition types
...
    const CONDITION_DATABAR = 'dataBar'; // add by fdream, 2019/03/19
...

PhpOffice\PhpSpreadsheet\Writer\Xlsx\Worksheet:462

    private function writeConditionalFormatting(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
    {
        $dataBars = [];
        // Conditional id
        $id = 1;

        // Loop through styles in the current worksheet
        foreach ($pSheet->getConditionalStylesCollection() as $cellCoordinate => $conditionalStyles) {
            foreach ($conditionalStyles as $conditional) {
                // WHY was this again?
                // if ($this->getParentWriter()->getStylesConditionalHashTable()->getIndexForHashCode($conditional->getHashCode()) == '') {
                //    continue;
                // }
                if ($conditional->getConditionType() == Conditional::CONDITION_DATABAR) {
                    $dataBars[] = $cellCoordinate;
                } elseif ($conditional->getConditionType() != Conditional::CONDITION_NONE) {
                    // conditionalFormatting
                    $objWriter->startElement('conditionalFormatting');
                    $objWriter->writeAttribute('sqref', $cellCoordinate);

                    // cfRule
                    $objWriter->startElement('cfRule');
                    $objWriter->writeAttribute('type', $conditional->getConditionType());
                    $objWriter->writeAttribute('dxfId', $this->getParentWriter()->getStylesConditionalHashTable()->getIndexForHashCode($conditional->getHashCode()));
                    $objWriter->writeAttribute('priority', $id++);

                    if (($conditional->getConditionType() == Conditional::CONDITION_CELLIS || $conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT)
                        && $conditional->getOperatorType() != Conditional::OPERATOR_NONE) {
                        $objWriter->writeAttribute('operator', $conditional->getOperatorType());
                    }

                    if ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
                        && $conditional->getText() !== null) {
                        $objWriter->writeAttribute('text', $conditional->getText());
                    }

                    if ($conditional->getStopIfTrue()) {
                        $objWriter->writeAttribute('stopIfTrue', '1');
                    }

                    if ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
                        && $conditional->getOperatorType() == Conditional::OPERATOR_CONTAINSTEXT
                        && $conditional->getText() !== null) {
                        $objWriter->writeElement('formula', 'NOT(ISERROR(SEARCH("' . $conditional->getText() . '",' . $cellCoordinate . ')))');
                    } elseif ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
                        && $conditional->getOperatorType() == Conditional::OPERATOR_BEGINSWITH
                        && $conditional->getText() !== null) {
                        $objWriter->writeElement('formula', 'LEFT(' . $cellCoordinate . ',' . strlen($conditional->getText()) . ')="' . $conditional->getText() . '"');
                    } elseif ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
                        && $conditional->getOperatorType() == Conditional::OPERATOR_ENDSWITH
                        && $conditional->getText() !== null) {
                        $objWriter->writeElement('formula', 'RIGHT(' . $cellCoordinate . ',' . strlen($conditional->getText()) . ')="' . $conditional->getText() . '"');
                    } elseif ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
                        && $conditional->getOperatorType() == Conditional::OPERATOR_NOTCONTAINS
                        && $conditional->getText() !== null) {
                        $objWriter->writeElement('formula', 'ISERROR(SEARCH("' . $conditional->getText() . '",' . $cellCoordinate . '))');
                    } elseif ($conditional->getConditionType() == Conditional::CONDITION_CELLIS
                        || $conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
                        || $conditional->getConditionType() == Conditional::CONDITION_EXPRESSION) {
                        foreach ($conditional->getConditions() as $formula) {
                            // Formula
                            $objWriter->writeElement('formula', $formula);
                        }
                    }

                    $objWriter->endElement();

                    $objWriter->endElement();
                }
            }
        }
        
        if (!empty($dataBars)) {
            // it won't work when there is more than 255 cells
            for ($l=count($dataBars), $i=0; $i < $l; $i += 255) {
                // conditionalFormatting
                $objWriter->startElement('conditionalFormatting');
                $objWriter->writeAttribute('sqref', implode(' ', array_slice($dataBars, $i, 255)));
                
                // cfRule
                $objWriter->startElement('cfRule');
                    $objWriter->writeAttribute('type', Conditional::CONDITION_DATABAR);
                    $objWriter->writeAttribute('priority', '1');
                
                    $objWriter->startElement('dataBar');
                    
                        $objWriter->startElement('cfvo');
                        $objWriter->writeAttribute('type', 'num');
                        $objWriter->writeAttribute('val', '0'); // min number here
                        $objWriter->endElement();
                        $objWriter->startElement('cfvo');
                        $objWriter->writeAttribute('type', 'num');
                        $objWriter->writeAttribute('val', '0.7'); // max number here
                        $objWriter->endElement();
                        $objWriter->startElement('color');
                        $objWriter->writeAttribute('rgb', 'FF3F3F3F'); // gradient color here. Still trying to figure out how solid color works
                        $objWriter->endElement();
                    
                    $objWriter->endElement();
                
                $objWriter->endElement();
                
                $objWriter->endElement();
            }
        }
    }

@lfernandes
Copy link

lfernandes commented Dec 5, 2019

Well, I unzip an excel file and figure out dataBar code myself. I finnaly did it with some ugly coding, maybe I will optimize them some other day.
PhpOffice\PhpSpreadsheet\Style\Conditional:15

class Conditional implements IComparable
{
    // Condition types
...
    const CONDITION_DATABAR = 'dataBar'; // add by fdream, 2019/03/19
...

PhpOffice\PhpSpreadsheet\Writer\Xlsx\Worksheet:462

    private function writeConditionalFormatting(XMLWriter $objWriter, PhpspreadsheetWorksheet $pSheet)
    {
        $dataBars = [];
        // Conditional id
        $id = 1;

        // Loop through styles in the current worksheet
        foreach ($pSheet->getConditionalStylesCollection() as $cellCoordinate => $conditionalStyles) {
            foreach ($conditionalStyles as $conditional) {
                // WHY was this again?
                // if ($this->getParentWriter()->getStylesConditionalHashTable()->getIndexForHashCode($conditional->getHashCode()) == '') {
                //    continue;
                // }
                if ($conditional->getConditionType() == Conditional::CONDITION_DATABAR) {
                    $dataBars[] = $cellCoordinate;
                } elseif ($conditional->getConditionType() != Conditional::CONDITION_NONE) {
                    // conditionalFormatting
                    $objWriter->startElement('conditionalFormatting');
                    $objWriter->writeAttribute('sqref', $cellCoordinate);

                    // cfRule
                    $objWriter->startElement('cfRule');
                    $objWriter->writeAttribute('type', $conditional->getConditionType());
                    $objWriter->writeAttribute('dxfId', $this->getParentWriter()->getStylesConditionalHashTable()->getIndexForHashCode($conditional->getHashCode()));
                    $objWriter->writeAttribute('priority', $id++);

                    if (($conditional->getConditionType() == Conditional::CONDITION_CELLIS || $conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT)
                        && $conditional->getOperatorType() != Conditional::OPERATOR_NONE) {
                        $objWriter->writeAttribute('operator', $conditional->getOperatorType());
                    }

                    if ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
                        && $conditional->getText() !== null) {
                        $objWriter->writeAttribute('text', $conditional->getText());
                    }

                    if ($conditional->getStopIfTrue()) {
                        $objWriter->writeAttribute('stopIfTrue', '1');
                    }

                    if ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
                        && $conditional->getOperatorType() == Conditional::OPERATOR_CONTAINSTEXT
                        && $conditional->getText() !== null) {
                        $objWriter->writeElement('formula', 'NOT(ISERROR(SEARCH("' . $conditional->getText() . '",' . $cellCoordinate . ')))');
                    } elseif ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
                        && $conditional->getOperatorType() == Conditional::OPERATOR_BEGINSWITH
                        && $conditional->getText() !== null) {
                        $objWriter->writeElement('formula', 'LEFT(' . $cellCoordinate . ',' . strlen($conditional->getText()) . ')="' . $conditional->getText() . '"');
                    } elseif ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
                        && $conditional->getOperatorType() == Conditional::OPERATOR_ENDSWITH
                        && $conditional->getText() !== null) {
                        $objWriter->writeElement('formula', 'RIGHT(' . $cellCoordinate . ',' . strlen($conditional->getText()) . ')="' . $conditional->getText() . '"');
                    } elseif ($conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
                        && $conditional->getOperatorType() == Conditional::OPERATOR_NOTCONTAINS
                        && $conditional->getText() !== null) {
                        $objWriter->writeElement('formula', 'ISERROR(SEARCH("' . $conditional->getText() . '",' . $cellCoordinate . '))');
                    } elseif ($conditional->getConditionType() == Conditional::CONDITION_CELLIS
                        || $conditional->getConditionType() == Conditional::CONDITION_CONTAINSTEXT
                        || $conditional->getConditionType() == Conditional::CONDITION_EXPRESSION) {
                        foreach ($conditional->getConditions() as $formula) {
                            // Formula
                            $objWriter->writeElement('formula', $formula);
                        }
                    }

                    $objWriter->endElement();

                    $objWriter->endElement();
                }
            }
        }
        
        if (!empty($dataBars)) {
            // it won't work when there is more than 255 cells
            for ($l=count($dataBars), $i=0; $i < $l; $i += 255) {
                // conditionalFormatting
                $objWriter->startElement('conditionalFormatting');
                $objWriter->writeAttribute('sqref', implode(' ', array_slice($dataBars, $i, 255)));
                
                // cfRule
                $objWriter->startElement('cfRule');
                    $objWriter->writeAttribute('type', Conditional::CONDITION_DATABAR);
                    $objWriter->writeAttribute('priority', '1');
                
                    $objWriter->startElement('dataBar');
                    
                        $objWriter->startElement('cfvo');
                        $objWriter->writeAttribute('type', 'num');
                        $objWriter->writeAttribute('val', '0'); // min number here
                        $objWriter->endElement();
                        $objWriter->startElement('cfvo');
                        $objWriter->writeAttribute('type', 'num');
                        $objWriter->writeAttribute('val', '0.7'); // max number here
                        $objWriter->endElement();
                        $objWriter->startElement('color');
                        $objWriter->writeAttribute('rgb', 'FF3F3F3F'); // gradient color here. Still trying to figure out how solid color works
                        $objWriter->endElement();
                    
                    $objWriter->endElement();
                
                $objWriter->endElement();
                
                $objWriter->endElement();
            }
        }
    }

Hello @fdreamsu , I'm trying to do the same, but it seems to don't be working anymore.

Can you please give me some help?

To apply i'm doing:

$conditional1->setConditionType(\PhpOffice\PhpSpreadsheet\Style\Conditional::CONDITION_DATABAR);
$conditionalStyles = $spreadsheet->getActiveSheet()->getStyle('G4')->getConditionalStyles();
$conditionalStyles[] = $conditional1;
$spreadsheet->getActiveSheet()->getStyle('G4')->setConditionalStyles($conditionalStyles);

Thanks in advance!

Current result:
POSTO_9_Resumo__35_

Expected:
POSTO_9_Resumo__35_

@cpnadal
Copy link

cpnadal commented Dec 6, 2019 via email

@fdreamsu
Copy link
Author

fdreamsu commented Dec 7, 2019

@lfernandes Sorry i don't have a clue. Haven't touch any of this for a long time.
I remember it was not too hard to understand how databar works in the excel file source code. You can simply unzip an excel file see for yourself. Just search "dataBar" in file xl/worksheets/sheet1.xml

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

4 participants