feat: excel importer
This commit is contained in:
@@ -1,44 +1,45 @@
|
||||
package dialogs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
)
|
||||
|
||||
var currentWindow *application.WebviewWindow
|
||||
|
||||
func Init(window *application.WebviewWindow) {
|
||||
if window == nil {
|
||||
panic("currentWindow is nil")
|
||||
}
|
||||
currentWindow = window
|
||||
}
|
||||
|
||||
func checkInit() {
|
||||
if currentWindow == nil {
|
||||
panic("Initialize dialogs package before use")
|
||||
}
|
||||
}
|
||||
|
||||
func InfoDialog(title string, message string) {
|
||||
checkInit()
|
||||
application.InfoDialog().AttachToWindow(currentWindow).SetTitle(title).SetMessage(message).Show()
|
||||
application.InfoDialog().SetTitle(title).SetMessage(message).Show()
|
||||
}
|
||||
|
||||
func WarningDialog(title string, message string) {
|
||||
checkInit()
|
||||
application.WarningDialog().AttachToWindow(currentWindow).SetTitle(title).SetMessage(message).Show()
|
||||
application.WarningDialog().SetTitle(title).SetMessage(message).Show()
|
||||
}
|
||||
|
||||
func ErrorDialog(title string, message string) {
|
||||
checkInit()
|
||||
application.ErrorDialog().AttachToWindow(currentWindow).SetTitle(title).SetMessage(message).Show()
|
||||
application.ErrorDialog().SetTitle(title).SetMessage(message).Show()
|
||||
}
|
||||
|
||||
func SaveFileDialog(title string, filename string) (string, error) {
|
||||
checkInit()
|
||||
selection, err := application.SaveFileDialog().AttachToWindow(currentWindow).SetFilename(filename).PromptForSingleSelection()
|
||||
selection, err := application.SaveFileDialog().SetFilename(filename).PromptForSingleSelection()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return selection, nil
|
||||
}
|
||||
|
||||
func OpenFileDialog(title string) (string, error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Println("Recovered in f", r)
|
||||
}
|
||||
}()
|
||||
dialog := application.OpenFileDialog()
|
||||
dialog.SetTitle(title)
|
||||
dialog.CanChooseDirectories(false)
|
||||
dialog.AddFilter("Электронные таблицы (.xlsx)", "*.xlsx")
|
||||
dialog.AddFilter("Электронные таблицы (.xls)", "*.xls")
|
||||
path, err := dialog.PromptForSingleSelection()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return path, nil
|
||||
}
|
||||
|
||||
53
internal/extras/excel/import.go
Normal file
53
internal/extras/excel/import.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package excel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/xuri/excelize/v2"
|
||||
)
|
||||
|
||||
type Importer struct {
|
||||
SheetName string
|
||||
Loader func(rowIndex int, row []string) error
|
||||
StartFromRowIdx int
|
||||
}
|
||||
|
||||
func ImportEntitiesFromSpreadsheet(path string, importers ...Importer) error {
|
||||
for _, importer := range importers {
|
||||
err := ImportEntitiesFromSpreadsheet(path, importer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ImportFromSpreadsheet(filepath string, importer Importer) error {
|
||||
f, err := excelize.OpenFile(filepath)
|
||||
defer func() {
|
||||
err := f.Close()
|
||||
if err != nil {
|
||||
slog.Error(fmt.Sprintf("Failed to close file: %s", err))
|
||||
}
|
||||
}()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rows, err := f.GetRows(importer.SheetName)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i, row := range rows {
|
||||
err := importer.Loader(i, row)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -13,7 +13,7 @@ type Post struct {
|
||||
Id uint `gorm:"primaryKey" ui:"hidden"`
|
||||
Text string `ui:"label:Текст"`
|
||||
Deadline int64 `ui:"label:Дедлайн;datatype:datetime;"`
|
||||
CreatedAt int64 `gorm:"autoCreateTime" ui:"readonly;datatype:datetime;"`
|
||||
CreatedAt int64 `gorm:"autoCreateTime" ui:"label:Время создания; readonly; datatype:datetime;"`
|
||||
AuthorId uint `ui:"hidden" gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
|
||||
Author Author `ui:"label:Автор; field:Name;"`
|
||||
PostTypeId uint `ui:"hidden"`
|
||||
|
||||
@@ -6,10 +6,11 @@ import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
"io"
|
||||
"log/slog"
|
||||
"os"
|
||||
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
)
|
||||
|
||||
type Migrator struct{}
|
||||
@@ -77,9 +78,9 @@ func Migrate(entities ...any) error {
|
||||
err = db.AutoMigrate(entities...)
|
||||
|
||||
if err != nil {
|
||||
slog.Info("Error occurred while migrations: %s. Recreate database...", err)
|
||||
slog.Info(fmt.Sprintf("Error occurred while migrations: %s, Recreate database...", err))
|
||||
if err = createDatabase(entities...); err != nil {
|
||||
slog.Error("Error occurred again: %s. Panic!", err)
|
||||
slog.Error(fmt.Sprintf("Error occurred again: %s. Panic!", err))
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
@@ -87,7 +88,7 @@ func Migrate(entities ...any) error {
|
||||
var hashAfterMigration string
|
||||
hashAfterMigration, err = CalculateFileSha256Checksum(database.Path)
|
||||
if err != nil {
|
||||
slog.Error("Failed to calc hash: %s", err)
|
||||
slog.Error(fmt.Sprintf("Failed to calc hash: %s", err))
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -95,7 +96,7 @@ func Migrate(entities ...any) error {
|
||||
slog.Info("Hashes before and after migrations are different. Recreate database...")
|
||||
err = createDatabase(entities...)
|
||||
if err != nil {
|
||||
slog.Error("Failed to create new database: %s", err)
|
||||
slog.Error(fmt.Sprintf("Failed to create new database: %s", err))
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,13 @@ package services
|
||||
import (
|
||||
"app/internal/dal"
|
||||
"app/internal/database"
|
||||
"app/internal/dialogs"
|
||||
"app/internal/extras/excel"
|
||||
"app/internal/models"
|
||||
"errors"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"gorm.io/gen/field"
|
||||
"gorm.io/gorm"
|
||||
@@ -59,3 +64,30 @@ func (service *PostTypeService) Count() (int64, error) {
|
||||
amount, err := dal.PostType.Count()
|
||||
return amount, err
|
||||
}
|
||||
|
||||
func (service *PostTypeService) ImportFromExcel() error {
|
||||
signal.Ignore(syscall.SIGSEGV)
|
||||
filepath, err := dialogs.OpenFileDialog("Импорт данных")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = excel.ImportFromSpreadsheet(filepath, excel.Importer{
|
||||
SheetName: "Тип поста",
|
||||
Loader: func(rowIndex int, row []string) error {
|
||||
id, err := strconv.Atoi(row[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
service.Create(PostType{
|
||||
Id: uint(id),
|
||||
Name: row[1],
|
||||
})
|
||||
return nil
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user