merge

Simple tool to quickly merge datasets for statistical analysis
Log | Files | Refs | README | LICENSE

commit 62255b57ee74f178acf0a542b02556e532ecb982
parent 4fb6febad659ee94eaac8aff4bf62e6a550bdfc5
Author: Nick Econopouly <wry@mm.st>
Date:   Sat,  4 Apr 2020 22:53:39 -0400

Add choice between Excel and CSV export

Diffstat:
A.gitignore | 2++
Mimport.go | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Mmain.go | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
3 files changed, 114 insertions(+), 22 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1 @@ +windows/+ \ No newline at end of file diff --git a/import.go b/import.go @@ -3,6 +3,12 @@ package main import ( "github.com/360EntSecGroup-Skylar/excelize" "log" + "strings" + "path/filepath" + "os" + "encoding/csv" + "fmt" + "runtime" ) // Dataset holds all of the variables and their data @@ -66,9 +72,22 @@ func (d *Dataset) removeUnusedTerms() { // return datasets // } -func exportDataset(d *Dataset, filepath string) { +// chooses which export function to call based on file extension +func exportDataset(d *Dataset, filename string) { + ext := strings.ToLower(filepath.Ext(filename)) + fmt.Println(ext) + switch ext { + case ".csv": + exportDatasetToCsv(d, filename) + break; + default: + exportDatasetToExcel(d, filename) + } +} + +func exportDatasetToExcel(d *Dataset, filepath string) { f := excelize.NewFile() - sheetName := f.GetSheetMap()[1] + sheetName := f.GetSheetMap()[1] for i, name := range d.terms { // write the term @@ -87,11 +106,45 @@ func exportDataset(d *Dataset, filepath string) { f.SetCellStr(sheetName, coord, value) } } - + err := f.SaveAs(filepath) if err != nil { log.Fatal("Unable to save file", err) } - + } +func exportDatasetToCsv(d *Dataset, filepath string) { + + err := os.RemoveAll(filepath) + if err != nil { + log.Fatal(err) + } + + f, err := os.Create(filepath) + if err != nil { + log.Fatal("Cannot open '%s': %s\n", filepath, err.Error()) + os.Exit(1) + } + defer f.Close() + + w := csv.NewWriter(f) + // fix windows line endings + if runtime.GOOS == "windows" { + w.UseCRLF = true + } + w.Write(d.terms) // first line contains the terms in order + for i := range d.data[d.terms[0]] { // use the length of the first column as the number of rows + var row []string + for _, value := range d.terms { // for each term + row = append(row, d.data[value][i]) // add the value of the term for the current row + } + + if err := w.Write(row); err != nil { // write the row + log.Fatal("error writing record to csv:", err) + } + } + w.Flush() + f.Sync() + +} diff --git a/main.go b/main.go @@ -19,7 +19,6 @@ import ( func windowSetup() *gtk.Window { os.Setenv("GSETTINGS_SCHEMA_DIR", ".\\share\\glib-2.0\\schemas") - // Set up GTK gtk.Init(&os.Args) @@ -42,7 +41,7 @@ func rebuildDatasetListBox(list *gtk.ListBox, filenames *[]string, window *gtk.W list.GetChildren().Foreach(func(item interface{}) { list.Remove(item.(*gtk.Widget)) }) - + for _, filename := range *filenames { // local variable necessary; see https://github.com/golang/go/wiki/CommonMistakes#using-goroutines-on-loop-iterator-variables path := filename @@ -52,7 +51,7 @@ func rebuildDatasetListBox(list *gtk.ListBox, filenames *[]string, window *gtk.W // show the filename text := newLabel(filename) - text.SetSelectable(true) + text.SetSelectable(true) box.PackStart(text, false, false, 0) // add the "Remove" button @@ -60,7 +59,7 @@ func rebuildDatasetListBox(list *gtk.ListBox, filenames *[]string, window *gtk.W if err != nil { log.Fatal("Unable to create removeButton", err) } - box.PackEnd(removeButton,false, false, 0) + box.PackEnd(removeButton,false, false, 0) trashImage, err := gtk.ImageNewFromFile("trash.png") removeButton.SetImage(trashImage) @@ -78,7 +77,7 @@ func rebuildDatasetListBox(list *gtk.ListBox, filenames *[]string, window *gtk.W func newHeadline(s string) *gtk.Label { if len(s) < 115 { var b bytes.Buffer - + for i := len(s); i < 115; i++ { b.WriteString(" ") } @@ -132,7 +131,7 @@ func pullExcel(path string) [][]string { func pullCSV(path string) [][]string { var rows [][]string - + f, err := os.Open(path) if err != nil { fmt.Printf("Cannot open '%s': %s\n", path, err.Error()) @@ -154,7 +153,7 @@ func pullCSV(path string) [][]string { func pullODS(path string) [][]string { var rows [][]string - + f, err := ods.Open(path) if err != nil { fmt.Println("trouble reading ods file", path,":",err) @@ -172,7 +171,7 @@ func pullODS(path string) [][]string { rows = d.Table[0].Strings() return rows - + } // see import.go for Dataset fields and methods used in this file @@ -221,7 +220,7 @@ func mergeDatasets(base *Dataset, new *Dataset) { func main() { window := windowSetup() - + // main box container mainBox, err := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 5) if err != nil { @@ -244,7 +243,7 @@ func main() { if err != nil { log.Fatal("unable to create addButton") } - mainBox.PackStart(addButton, false, false, 0) + mainBox.PackStart(addButton, false, false, 0) // native file chooser addDatasetDialog, err := gtk.FileChooserNativeDialogNew("open",window,gtk.FILE_CHOOSER_ACTION_OPEN,"open","cancel") @@ -282,19 +281,57 @@ func main() { errorLabel := newLabel("") mainBox.PackStart(errorLabel, false, false, 0) - + // another native file chooser saveDialog, err := gtk.FileChooserNativeDialogNew("save",window,gtk.FILE_CHOOSER_ACTION_SAVE,"save","cancel") - + + // filter for acceptable filetypes to save to + CsvFilter, err := gtk.FileFilterNew() + CsvFilter.AddPattern("*.csv") + CsvFilter.SetName("Comma Separated Values") + + AllFilter, err := gtk.FileFilterNew() + AllFilter.AddPattern("*") + AllFilter.SetName("All File Types") + + ExcelFilter, err := gtk.FileFilterNew() + ExcelFilter.AddPattern( + + + + + + + + + + + + + + "*.xlsx") + ExcelFilter.SetName("Microsoft Excel") + // saveFilter.AddMimeType("ods") + // saveFilter.AddMimeType("xlsx") + + saveDialog.AddFilter(CsvFilter) + saveDialog.AddFilter(ExcelFilter) + saveDialog.AddFilter(AllFilter) + saveDialog.SetFilter(AllFilter) + saveDialog.SetFilename("merged.xlsx") + + saveDialog.SetDoOverwriteConfirmation(true) + _, err = mergeButton.Connect("clicked", func() { + // clear old error errorLabel.SetText("") - + if goodFileExtensions(filepaths) { _ = saveDialog.Run() outputFile := saveDialog.GetFilename() - if outputFile != ""{ + if outputFile != "" { // supported file extensions and their associated function for pulling the raw data fileFormat := map[string]func(string) [][]string{ @@ -320,7 +357,7 @@ func main() { datasets[name] = ImportDataset(name, data) } } - + // merge them into a single Dataset var dataset Dataset dataset.height = 1 // row of terms, even though it's empty @@ -328,16 +365,16 @@ func main() { for _, d := range datasets { mergeDatasets(&dataset,d) } - + // export dataset exportDataset(&dataset, outputFile) } - + } else { errorLabel.SetText("There was a problem with the files you chose. Make sure to choose supported spreadsheet formats.") } }) - + window.Add(mainBox) window.ShowAll()