Skip to content

string labels dumped to Excel should be formatted as strings #646

Description

@gdementen
>>> arr = ndtest('a=10E01,10E03')
>>> arr.to_excel()

produces something like:

 a | 1.00E+02 | 1.00E+04
   |        0 |        1

This is not a visual transformation, it actually converts the values to numbers (whatever the actual dtype of labels were -- .dump() converts numpy types to raw Python types anyway)

>>> arr.a.labels.dtype
dtype('<U5')
>>> arr.dump()
[['a', '10E01', '10E03'], ['', 0, 1]]

The solution is to set NumberFormat on the target cells before pasting the values (https://github.com/ZoomerAnalytics/xlwings/issues/436).

>>> wb = open_excel()
>>> # produces bad result
>>> wb[0]['A1'] = '10E03'
>>> # produces good result
>>> wb[0]['A2'].api.NumberFormat = "@"
>>> wb[0]['A2'] = '10E03'

Note that set_labels (currently) returns object arrays. This should be irrelevant when we go via .dump(), which is always the case, I think (when using wb[0] = array, .dump() is called automatically).

>>> ndtest(3).set_labels('a', {'a1': '10E03'}).a.labels.dtype
dtype('O')

Ideally, this should be fixed in xlwings.

Honestly, this issue seems easy to fix for small arrays (by scanning through each value and setting the format accordingly) but hard to do efficiently (set the format in chunks). Maybe .dump should not return a simple list of list but a custom object which retains the notion of axes etc. so that we can set the format for each axis in a single operation?

Activity

  1. added this to the 0.29 milestone on Jun 11, 2018
  2. alixdamman commented on Jun 21, 2018

    @alixdamman
    Collaborator

    Actually, the problem comes also at loading. So, the solution cannot limited to update the dump method.

  3. gdementen commented on Jun 21, 2018

    @gdementen
    ContributorAuthor

    I cannot reproduce the problem during load. Could you provide a test case?

    arr = ndtest('a=10E01,10E03')
    wb = open_excel()
    wb[0]['A1:C2'].api.NumberFormat = "@"
    wb[0]['A1'] = arr.dump()
    res1 = wb[0].load()
    res2 = read_excel(-1)

    both res1 and res2 contain the correct labels.

  4. modified the milestones: 0.29, 0.30 on Jun 26, 2018
  5. modified the milestones: 0.30, 0.31 on Jan 31, 2019
  6. removed this from the 0.31 milestone on Aug 1, 2019
  7. added this to the 0.32 milestone on Aug 13, 2019
  8. alanmanning commented on Aug 22, 2019

    @alanmanning

    One possible work-around: prepending the strings with an apostrophe.

    test1 = ['1e10','08-Nov-19','1234.0','text']
    sheet = wb.sheets['Sheet1']
    sheet.range('A1').value = test1 #get number, date, number, text types in A1:D1:
    test2 = ["'"+x for x in test1]
    sheet.range('E1').value = test2 #get text, text, text types in E1:H1
    # Note: text types in E1:G1 are preceded by an apostrophe
  9. gdementen commented on Aug 23, 2019

    @gdementen
    ContributorAuthor

    Hi @apmanning. IIRC, this works but is annoying because you then have to change the values when reading them back.

    Also, as a user I find it ugly to have apostrophes in my Excel files when it's not necessary. Since there is another way (formatting as numbers) which has fewer disadvantages, I would rather implement that. Or do you see any reason why/case where the apostrophe method is better than the numberformat method?

  10. removed this from the 0.32 milestone on Sep 24, 2019
  11. gdementen commented on Jan 5, 2021

    @gdementen
    ContributorAuthor

    Contrary to what I thought, one does not have to remove the ' when reading the values back. Either Excel or xlwings is doing that for us. I guess that's the easiest workaround then. It's just kinda ugly to have them in Excel but well...

    >>> arr = ndtest('a=10E01,10E03')
    >>> def prefix_label(label):
    ...     return "'" + label
    >>> arr.set_labels('a', prefix_label).to_excel()
    >>> # or (equivalently but less readable)
    >>> # arr.set_labels('a', "'".__add__).to_excel()
    >>> res = read_excel(-1)
    >>> res.equals(arr)
    True
  12. added this to the 0.34 milestone on Jul 30, 2021
  13. modified the milestones: 0.34, 0.35 on Sep 13, 2022
  14. modified the milestones: 0.35, 0.36 on Sep 11, 2023
  15. modified the milestones: 0.36, 0.37 on Oct 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions