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

Border style unintentionally shared between CellStyle instances #288

Closed
vpstuart opened this issue Dec 20, 2019 · 6 comments
Closed

Border style unintentionally shared between CellStyle instances #288

vpstuart opened this issue Dec 20, 2019 · 6 comments
Labels
Milestone

Comments

@vpstuart
Copy link
Contributor

vpstuart commented Dec 20, 2019

I have found in an application that the border formatting in XSSFCellStyle is a bit broken. It results in accidentally sharing a CT_Border instance.

From https://github.com/tonyqus/npoi/blob/master/ooxml/XSSF/UserModel/XSSFCellStyle.cs#L252

        public BorderStyle BorderBottom
        {
            get
            {
                if (!_cellXf.applyBorder) return BorderStyle.None;

                int idx = (int)_cellXf.borderId;
                CT_Border ct = _stylesSource.GetBorderAt(idx).GetCTBorder();
                if (!ct.IsSetBottom())
                {
                    return BorderStyle.None;
                }
                else
                {
                    return (BorderStyle)ct.bottom.style;
                }
            }
            set
            {
                CT_Border ct = GetCTBorder();
                CT_BorderPr pr = ct.IsSetBottom() ? ct.bottom : ct.AddNewBottom();
                if (value == BorderStyle.None) 
                    ct.UnsetBottom();
                else 
                    pr.style = (ST_BorderStyle)value;

                int idx = _stylesSource.PutBorder(new XSSFCellBorder(ct, _theme));

                _cellXf.borderId = (uint)idx;
                _cellXf.applyBorder = (true);
            }
        }

Each of the border setters has the same but, I have chosen BorderBottom as an example.

The first time you assign a value to a border property. E.g. cell.BorderBottom = BorderStyle.Thin; it will create a CT_Border object, assign the border to it and then call _stylesSource.PutBorder(new XSSFCellBorder(ct, _theme)) which will store the border object and return an ID.

If it finds a matching CT_Border it will return that instances id, causing it to be shared.

This seems to be from here:
https://github.com/tonyqus/npoi/blob/master/ooxml/XSSF/Model/StylesTable.cs#L285

        public int PutBorder(XSSFCellBorder border)
        {
            int idx = borders.IndexOf(border);
            if (idx != -1)
            {
                return idx;
            }
            borders.Add(border);
            border.SetThemesTable(theme);
            return borders.Count - 1;
        }

Using borders.IndexOf(border) will search by the current value of the border. The XSSFCellBorder class implements equality based on the XML value of the CT_Border.

I think the easiest and possibly best solution would be to delete the 5 lines:

            int idx = borders.IndexOf(border);
            if (idx != -1)
            {
                return idx;
            }

I'm not a regular contributer here, but if it would help I can try and put together a PR.

Warm Regards,
Stuart

@vpstuart
Copy link
Contributor Author

On second look that will result in the pool of borders growing each time. Perhaps instead CT_Border ct = GetCTBorder(); needs to always make a clone.

@tonyqus
Copy link
Member

tonyqus commented Jun 22, 2021

@asypost After review, your issue is mainly about the CopyRowTo. I suggest you create a new issue for your case.

@tonyqus tonyqus added the bug label Jun 22, 2021
@yorban
Copy link

yorban commented Aug 18, 2021

My team using NPOI has also experienced many headaches due to this issue.

@tonyqus tonyqus changed the title Border style unintentionally shared between XSSFStyle instances Border style unintentionally shared between CellStyle instances Oct 18, 2021
@tonyqus tonyqus modified the milestones: NPOI 2.5.5, NPOI 2.5.6 Oct 22, 2021
@tonyqus
Copy link
Member

tonyqus commented Feb 4, 2022

Can you test NPOI 2.5.5? I think this was somewhat fixed. @yorban

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

No branches or pull requests

4 participants
@tonyqus @yorban @vpstuart and others