tealeg / xlsx

Go library for reading and writing XLSX files.
Other
5.81k stars 808 forks source link

Fourth time a cell is set it won't be written to if it's not the last cell written to #790

Closed ryancurrah closed 1 month ago

ryancurrah commented 8 months ago

Consistently in a new sheet the 4th time I try to write into a cell it does not get written to unless it is the last time I write to a cell.

I'm using v3.3.4 of the module. Below I have some code to reproduce the issue. In the below example on the lines err = setCellValueString(firstSheet, "A6", "BLARGGGGGG") you will see in the first sheet cell A6 does not get written, but in the second sheet it does because it is the last cell written to.

package main

import (
    "log"
    "sync"
    "time"

    "github.com/tealeg/xlsx/v3"
    "golang.org/x/sync/errgroup"
)

type listTagsData struct {
    NumOfTags int
    Duration  time.Duration
}

var (
    getCatalogDuration    time.Duration
    listTagsTotalDuration time.Duration
    listTagsDurations     = map[string]listTagsData{}
    mu                    = sync.RWMutex{}
)

func main() {
    getCatalogStartTime := time.Now()
    time.Sleep(time.Second * 2)
    getCatalogDuration = time.Since(getCatalogStartTime)

    g := new(errgroup.Group)
    g.SetLimit(8)

    listTagsTotalStartTime := time.Now()

    for _, image := range []string{"docker.acme.com/test1", "docker.acme.com/test2"} {
        image := image
        g.Go(func() error {
            listTagsStart := time.Now()
            time.Sleep(time.Millisecond * 200)
            mu.Lock()
            listTagsDurations[image] = listTagsData{
                NumOfTags: 1,
                Duration:  time.Since(listTagsStart),
            }
            mu.Unlock()

            return nil
        })
    }

    if err := g.Wait(); err != nil {
        log.Fatal(err)
    }

    listTagsTotalDuration = time.Since(listTagsTotalStartTime)

    f := xlsx.NewFile()

    firstSheet, err := f.AddSheet("first_Sheet")
    if err != nil {
        log.Fatal(err)
    }

    err = setCellValueString(firstSheet, "A1", "actions")
    if err != nil {
        log.Fatal(err)
    }

    err = setCellValueString(firstSheet, "A2", "get_catalog")
    if err != nil {
        log.Fatal(err)
    }

    err = setCellValueString(firstSheet, "A3", "list_tags")
    if err != nil {
        log.Fatal(err)
    }

    // This cell wont actually be created and if dont add this line the next cell wont be created, I dont know why.
    // You can replace A6 with any cell and it wont be created.
    err = setCellValueString(firstSheet, "A6", "BLARGGGGGG")
    if err != nil {
        log.Fatal(err)
    }

    err = setCellValueString(firstSheet, "A4", "total")
    if err != nil {
        log.Fatal(err)
    }

    err = setCellValueString(firstSheet, "B1", "duration")
    if err != nil {
        log.Fatal(err)
    }

    err = setCellValueString(firstSheet, "B2", getCatalogDuration.Round(time.Millisecond).String())
    if err != nil {
        log.Fatal(err)
    }

    err = setCellValueString(firstSheet, "B3", listTagsTotalDuration.Round(time.Millisecond).String())
    if err != nil {
        log.Fatal(err)
    }

    err = setCellValueString(firstSheet, "B4", (listTagsTotalDuration + getCatalogDuration).Round(time.Millisecond).String())
    if err != nil {
        log.Fatal(err)
    }

    secondSheet, err := f.AddSheet("second_sheet")
    if err != nil {
        log.Fatal(err)
    }

    err = setCellValueString(secondSheet, "A1", "actions")
    if err != nil {
        log.Fatal(err)
    }

    err = setCellValueString(secondSheet, "A2", "get_catalog")
    if err != nil {
        log.Fatal(err)
    }

    err = setCellValueString(secondSheet, "A3", "list_tags")
    if err != nil {
        log.Fatal(err)
    }

    // Reproduces the same issue in first sheet IF the below lines are uncommented. Otherwise this cell will be created if it is last.
    err = setCellValueString(secondSheet, "A6", "BLARGGGGGG")
    if err != nil {
        log.Fatal(err)
    }

    // err = setCellValueString(fourthSheet, "A4", "total")
    // if err != nil {
    //  log.Fatal(err)
    // }

    // err = setCellValueString(fourthSheet, "B1", "duration")
    // if err != nil {
    //  log.Fatal(err)
    // }

    // err = setCellValueString(fourthSheet, "B2", getCatalogDuration.Round(time.Millisecond).String())
    // if err != nil {
    //  log.Fatal(err)
    // }

    // err = setCellValueString(fourthSheet, "B3", listTagsTotalDuration.Round(time.Millisecond).String())
    // if err != nil {
    //  log.Fatal(err)
    // }

    // err = setCellValueString(fourthSheet, "B4", (listTagsTotalDuration + getCatalogDuration).Round(time.Millisecond).String())
    // if err != nil {
    //  log.Fatal(err)
    // }

    if err = f.Save("docker_registry_perf.xlsx"); err != nil {
        log.Fatal(err)
    }

    firstSheet.Close()
    secondSheet.Close()
}

func setCellValueString(sheet *xlsx.Sheet, cell, value string) error {
    x, y, err := xlsx.GetCoordsFromCellIDString(cell)
    if err != nil {
        return err
    }

    c, err := sheet.Cell(y, x)
    if err != nil {
        return err
    }

    c.SetString(value)

    return nil
}
tealeg commented 8 months ago

@ryancurrah alrighty - that already feels like it's going to be a fun one ;-)

ryancurrah commented 8 months ago

@ryancurrah alrighty - that already feels like it's going to be a fun one ;-)

Yeah it's interesting I'm currently running this example in Goland with a debugger setting breakpoints in the library trying to understand where this issue is occurring.

ryancurrah commented 8 months ago

The coordinates seem correct from GetCoordsFromCellIDString. See screenshot.

Screenshot 2023-11-02 at 11 51 30 AM
ryancurrah commented 8 months ago

It appears row first_Sheet:000005 is never created, even though I call c.SetString on a cell in that row. Breakpoint is if err = f.Save("docker_registry_perf.xlsx"); err != nil {

Screenshot 2023-11-02 at 12 06 13 PM
github-actions[bot] commented 6 months ago

Stale issue message

github-actions[bot] commented 4 months ago

Stale issue message

github-actions[bot] commented 2 months ago

Stale issue message