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

Table data extraction #1639

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

Conversation

sides-flow
Copy link

@sides-flow sides-flow commented Aug 31, 2023

  • Added method GetTableData to extract raw table values
  • Added method GetTableColumns to extract values with their columns

I'm not so sure about the naming of these functions, feel free to rename them however you want

PR Details

I needed to extract values from a table, and I found out it is hard for the user to use the GetTables to actually access the data (need to convert the range to coordinates and manually walk the cells).
So I added a couple of methods to access the table's values with structured ways.

Description

Related Issue

Motivation and Context

How Has This Been Tested

I added the unit test for the methods I created.
I ran all the tests locally.

Types of changes

  • Docs change / refactoring / dependency upgrade
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

Added method GetTableData to extract raw table values
Added method GetTableColumns to extract values with their columns
@xuri xuri added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Aug 31, 2023
@sides-flow
Copy link
Author

Anything else needed to merge this in? @xuri

Copy link
Member

@xuri xuri left a comment

Choose a reason for hiding this comment

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

Sorry for my late reply. Thanks for your pull request. Unfortunately, due to the principle of minimum availability, I didn't suggest introducing these functions to keep the library core and easy. Anyone can easily make a custom function to get cells in the table range by themselves: table cell value, table cell formula, table cell style, table cell conditional formatting rules, etc., The developers can implement that by the wrapper or composite the existing exported functions.

@sides-flow
Copy link
Author

Sorry for my late reply. Thanks for your pull request. Unfortunately, due to the principle of minimum availability, I didn't suggest introducing these functions to keep the library core and easy. Anyone can easily make a custom function to get cells in the table range by themselves: table cell value, table cell formula, table cell style, table cell conditional formatting rules, etc., The developers can implement that by the wrapper or composite the existing exported functions.

It cannot be implemented by the developer since there is no way to access the coordinates of the table by its range (in-order to iterate over the table's cells). I agree that it extends functionality of the library, but as of now I don't see a way of doing it with the current API (unless I copy code from the library to my code, which defeats the purpose)

@xuri
Copy link
Member

xuri commented Feb 4, 2024

Excelize library provides a set of utility functions to convert between cell reference and column/row number, so the user can get table range, convert the range to coordinates, and walk the cells by simple code just like in this pull request. Users can get table cell value, table cell formula, table cell style, table cell conditional formatting rules, formula, etc. when walking the cells, so I do not suggest adding a series function for each scenario of the above: GetTableData, GetTableCellStyle, GetTableCellConditionalFormatting, GetTableCellFormula, etc., Here is a standalone example for get cell value in table range base on this pull request:

package main

import (
    "fmt"
    "math/rand"
    "strings"

    "github.com/xuri/excelize/v2"
)

func main() {
    f := excelize.NewFile()
    defer func() {
        if err := f.Close(); err != nil {
            fmt.Println(err)
        }
    }()
    // Generate random numbers and set cell values in the table range
    for rowNum := 2; rowNum <= 5; rowNum++ {
        row := make([]interface{}, 5)
        for colID := 0; colID < 5; colID++ {
            row[colID] = rand.Intn(100)
        }
        cell, err := excelize.CoordinatesToCellName(1, rowNum)
        if err != nil {
            fmt.Println(err)
            return
        }
        if err := f.SetSheetRow("Sheet1", cell, &row); err != nil {
            fmt.Println(err)
            return
        }
    }
    // Add a table
    if err := f.AddTable("Sheet1", &excelize.Table{
        Range:             "A1:E5",
        Name:              "table",
        StyleName:         "TableStyleMedium2",
        ShowFirstColumn:   true,
        ShowLastColumn:    true,
        ShowColumnStripes: true,
    }); err != nil {
        fmt.Println(err)
        return
    }
    tables, err := f.GetTables("Sheet1")
    if err != nil {
        fmt.Println(err)
        return
    }
    for _, table := range tables {
        // Get table range, convert the range to coordinates
        tableRange := strings.Split(table.Range, ":")
        if len(tableRange) != 2 {
            return
        }
        fromCol, fromRow, err := excelize.CellNameToCoordinates(tableRange[0])
        if err != nil {
            fmt.Println(err)
            return
        }
        toCol, toRow, err := excelize.CellNameToCoordinates(tableRange[1])
        if err != nil {
            fmt.Println(err)
            return
        }
        // Walk the cells of the table
        for rowNum := fromRow; rowNum <= toRow; rowNum++ {
            for colNum := fromCol; colNum <= toCol; colNum++ {
                cell, err := excelize.CoordinatesToCellName(colNum, rowNum)
                if err != nil {
                    fmt.Println(err)
                    return
                }
                val, err := f.GetCellValue("Sheet1", cell)
                if err != nil {
                    fmt.Println(err)
                    return
                }
                fmt.Print(val, "\t")
            }
            fmt.Println()
        }
    }
    if err := f.SaveAs("Book1.xlsx"); err != nil {
        fmt.Println(err)
    }
}

@xuri xuri force-pushed the master branch 2 times, most recently from 79958aa to 0c3dfb1 Compare May 25, 2024 17:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants