@ -1,6 +1,7 @@
package tools
import (
"encoding/json"
"fmt"
"github.com/xuri/excelize/v2"
_ "image/gif"
@ -27,7 +28,7 @@ const (
bucketAnswers = "squizanswer"
)
func WriteDataToExcel ( buffer io . Writer , questions [ ] model . Question , answers [ ] model . Answer ) error {
func WriteDataToExcel ( buffer io . Writer , questions [ ] model . Question , answers [ ] model . Answer , s3Prefix string ) error {
file := excelize . NewFile ( )
sheet := "Sheet1"
@ -40,6 +41,36 @@ func WriteDataToExcel(buffer io.Writer, questions []model.Question, answers []mo
return questions [ i ] . Page < questions [ j ] . Page
} )
headers , mapQueRes := prepareHeaders ( questions )
for col , header := range headers {
cell := ToAlphaString ( col + 1 ) + "1"
if err := file . SetCellValue ( sheet , cell , header ) ; err != nil {
return err
}
}
sort . Slice ( answers , func ( i , j int ) bool {
return answers [ i ] . QuestionId < answers [ j ] . QuestionId
} )
standart , results := categorizeAnswers ( answers )
var wg sync . WaitGroup
row := 2
for session := range results {
wg . Add ( 1 )
go func ( session string , response [ ] model . Answer , row int ) {
defer wg . Done ( )
processSession ( file , sheet , session , s3Prefix , response , results , questions , mapQueRes , headers , row )
} ( session , standart [ session ] , row )
row ++
}
wg . Wait ( )
return file . Write ( buffer )
}
func prepareHeaders ( questions [ ] model . Question ) ( [ ] string , map [ uint64 ] string ) {
headers := [ ] string { "Данные респондента" }
mapQueRes := make ( map [ uint64 ] string )
@ -52,27 +83,14 @@ func WriteDataToExcel(buffer io.Writer, questions []model.Question, answers []mo
}
}
}
headers = append ( headers , "Результат" )
return headers , mapQueRes
}
for col , header := range headers {
cell := ToAlphaString ( col + 1 ) + "1"
if err := file . SetCellValue ( sheet , cell , header ) ; err != nil {
return err
}
}
sort . Slice ( answers , func ( i , j int ) bool {
return answers [ i ] . QuestionId < answers [ j ] . QuestionId
} )
// мапа для хранения обычных ответов респондентов
func categorizeAnswers ( answers [ ] model . Answer ) ( map [ string ] [ ] model . Answer , map [ string ] model . Answer ) {
standart := make ( map [ string ] [ ] model . Answer )
// мапа для хранения данных респондентов
results := make ( map [ string ] model . Answer )
// заполняем мапу ответами и данными респондентов
for _ , answer := range answers {
if answer . Result {
results [ answer . Session ] = answer
@ -80,104 +98,110 @@ func WriteDataToExcel(buffer io.Writer, questions []model.Question, answers []mo
standart [ answer . Session ] = append ( standart [ answer . Session ] , answer )
}
}
return standart , results
}
processSession := func ( session string , response [ ] model . Answer , row int ) {
defer func ( ) {
if r := recover ( ) ; r != nil {
fmt . Println ( "Recovered from panic:" , r )
}
} ( )
if err := file . SetCellValue ( sheet , "A" + strconv . Itoa ( row ) , results [ session ] . Content ) ; err != nil {
fmt . Println ( err . Error ( ) )
func processSession ( file * excelize . File , sheet , session , s3Prefix string , response [ ] model . Answer , results map [ string ] model . Answer , questions [ ] model . Question , mapQueRes map [ uint64 ] string , headers [ ] string , row int ) {
defer func ( ) {
if r := recover ( ) ; r != nil {
fmt . Println ( "Recovered from panic:" , r )
}
count := 2
for _ , q := range questions {
if ! q . Deleted && q . Type != model . TypeResult {
index := binarySearch ( response , q . Id )
if index != - 1 {
cell := ToAlphaString ( count ) + strconv . Itoa ( row )
tipe := FileSearch ( response [ index ] . Content )
noAccept := make ( map [ string ] struct { } )
todoMap := make ( map [ string ] string )
if tipe != "Text" && q . Type == model . TypeImages || q . Type == model . TypeVarImages {
urle := ExtractImageURL ( response [ index ] . Content )
urlData := strings . Split ( urle , " " )
if len ( urlData ) == 1 {
u , err := url . Parse ( urle )
if err == nil && u . Scheme != "" && u . Host != "" {
picture , err := downloadImage ( urle )
if err != nil {
fmt . Println ( err . Error ( ) )
}
file . SetColWidth ( sheet , ToAlphaString ( count ) , ToAlphaString ( count ) , 50 )
file . SetRowHeight ( sheet , row , 150 )
if err := file . AddPictureFromBytes ( sheet , cell , picture ) ; err != nil {
fmt . Println ( err . Error ( ) )
}
noAccept [ response [ index ] . Content ] = struct { } { }
} else {
todoMap [ response [ index ] . Content ] = cell
}
} else {
todoMap [ response [ index ] . Content ] = cell
}
} else if tipe != "Text" && q . Type == model . TypeFile {
urle := ExtractImageURL ( response [ index ] . Content )
display , tooltip := urle , urle
if err := file . SetCellValue ( sheet , cell , response [ index ] . Content ) ; err != nil {
fmt . Println ( err . Error ( ) )
}
if err := file . SetCellHyperLink ( sheet , cell , urle , "External" , excelize . HyperlinkOpts {
Display : & display ,
Tooltip : & tooltip ,
} ) ; err != nil {
fmt . Println ( err . Error ( ) )
}
noAccept [ response [ index ] . Content ] = struct { } { }
} else {
todoMap [ response [ index ] . Content ] = cell
}
for cnt , cel := range todoMap {
if _ , ok := noAccept [ cnt ] ; ! ok {
if err := file . SetCellValue ( sheet , cel , cnt ) ; err != nil {
fmt . Println ( err . Error ( ) )
}
}
}
} ( )
} else {
cell := ToAlphaString ( count ) + strconv . Itoa ( row )
if err := file . SetCellValue ( sheet , cell , "-" ) ; err != nil {
fmt . Println ( err . Error ( ) )
}
if err := file . SetCellValue ( sheet , "A" + strconv . Itoa ( row ) , results [ session ] . Content ) ; err != nil {
fmt . Println ( err . Error ( ) )
}
count := 2
for _ , q := range questions {
if ! q . Deleted && q . Type != model . TypeResult {
cell := ToAlphaString ( count ) + strconv . Itoa ( row )
index := binarySearch ( response , q . Id )
if index != - 1 {
handleAnswer ( file , sheet , cell , s3Prefix , response [ index ] , q , count , row )
} else {
if err := file . SetCellValue ( sheet , cell , "-" ) ; err != nil {
fmt . Println ( err . Error ( ) )
}
count ++
}
count ++
}
}
cell := ToAlphaString ( len ( headers ) ) + strconv . Itoa ( row )
if err := file . SetCellValue ( sheet , cell , mapQueRes [ results [ session ] . QuestionId ] ) ; err != nil {
fmt . Println ( err . Error ( ) )
}
}
func handleAnswer ( file * excelize . File , sheet , cell , s3Prefix string , answer model . Answer , question model . Question , count , row int ) {
tipe := FileSearch ( answer . Content )
noAccept := make ( map [ string ] struct { } )
todoMap := make ( map [ string ] string )
if tipe != "Text" && question . Type == model . TypeImages || question . Type == model . TypeVarImages {
handleImage ( file , sheet , cell , answer . Content , count , row , noAccept , todoMap )
} else if question . Type == model . TypeFile {
handleFile ( file , sheet , cell , answer . Content , s3Prefix , noAccept )
} else {
todoMap [ answer . Content ] = cell
}
for cnt , cel := range todoMap {
if _ , ok := noAccept [ cnt ] ; ! ok {
if err := file . SetCellValue ( sheet , cel , cnt ) ; err != nil {
fmt . Println ( err . Error ( ) )
}
}
cell := ToAlphaString ( len ( headers ) ) + strconv . Itoa ( row )
if err := file . SetCellValue ( sheet , cell , mapQueRes [ results [ session ] . QuestionId ] ) ; err != nil {
fmt . Println ( err . Error ( ) )
}
}
func handleImage ( file * excelize . File , sheet , cell , content string , count , row int , noAccept map [ string ] struct { } , todoMap map [ string ] string ) {
var res model . ImageContent
err := json . Unmarshal ( [ ] byte ( content ) , & res )
if err != nil {
res . Image = content
}
urle := ExtractImageURL ( res . Image )
urlData := strings . Split ( urle , " " )
if len ( urlData ) == 1 {
u , err := url . Parse ( urle )
if err == nil && u . Scheme != "" && u . Host != "" {
picture , err := downloadImage ( urle )
if err != nil {
fmt . Println ( err . Error ( ) )
}
file . SetColWidth ( sheet , ToAlphaString ( count ) , ToAlphaString ( count ) , 50 )
file . SetRowHeight ( sheet , row , 150 )
if err := file . AddPictureFromBytes ( sheet , cell , picture ) ; err != nil {
fmt . Println ( err . Error ( ) )
}
noAccept [ content ] = struct { } { }
} else {
todoMap [ content ] = cell
}
} else {
todoMap [ content ] = cell
}
}
func handleFile ( file * excelize . File , sheet , cell , content , s3Prefix string , noAccept map [ string ] struct { } ) {
urle := content
if urle != "" && ! strings . HasPrefix ( urle , "https" ) {
urle = s3Prefix + urle
}
row := 2
var wg sync . WaitGroup
for session , _ := range results {
wg . Add ( 1 )
go func ( session string , response [ ] model . Answer , row int ) {
defer wg . Done ( )
processSession ( session , standart [ session ] , row )
} ( session , standart [ session ] , row )
row ++
}
wg . Wait ( )
fmt . Println ( "ORRRRR" , urle , s3Prefix )
display , tooltip := urle , urle
if err := file . Write ( buffer ) ; err != nil {
return err
if err := file . SetCellValue ( sheet , cell , urle ) ; err != nil {
fmt . Println ( err . Error ( ) )
}
return nil
if err := file . SetCellHyperLink ( sheet , cell , urle , "External" , excelize . HyperlinkOpts {
Display : & display ,
Tooltip : & tooltip ,
} ) ; err != nil {
fmt . Println ( err . Error ( ) )
}
noAccept [ content ] = struct { } { }
}
func binarySearch ( answers [ ] model . Answer , questionID uint64 ) int {
@ -283,141 +307,3 @@ func ExtractImageURL(htmlContent string) string {
}
return htmlContent
}
//func WriteDataToExcel(buffer io.Writer, questions []model.Question, answers []model.Answer) error {
// file := excelize.NewFile()
// sheet := "Sheet1"
//
// _, err := file.NewSheet(sheet)
// if err != nil {
// return err
// }
//
// sort.Slice(questions, func(i, j int) bool {
// return questions[i].Page > questions[j].Page
// })
//
// headers := []string{"Данные респондента"}
// mapQueRes := make(map[uint64]string)
//
// for _, q := range questions {
// if !q.Deleted {
// if q.Type == model.TypeResult {
// mapQueRes[q.Id] = q.Title + "\n" + q.Description
// } else {
// headers = append(headers, q.Title)
// }
// }
// }
//
// headers = append(headers, "Результат")
//
// // добавляем заголовки в первую строку
// for col, header := range headers {
// cell := ToAlphaString(col+1) + "1"
// if err := file.SetCellValue(sheet, cell, header); err != nil {
// return err
// }
// }
//
// // мапа для хранения обычных ответов респондентов
// standart := make(map[string][]model.Answer)
//
// // мапа для хранения данных респондентов
// results := make(map[string]model.Answer)
//
// // заполняем мапу ответами и данными респондентов
// for _, answer := range answers {
// if answer.Result {
// results[answer.Session] = answer
// } else {
// standart[answer.Session] = append(standart[answer.Session], answer)
// }
// }
//
// // записываем данные в файл
// row := 2
// for session, _ := range results {
// response := standart[session]
// if err := file.SetCellValue(sheet, "A"+strconv.Itoa(row), results[session].Content); err != nil {
// return err
// }
// count := 2
// for _, q := range questions {
// if !q.Deleted && q.Type != model.TypeResult {
// sort.Slice(response, func(i, j int) bool {
// return response[i].QuestionId < response[j].QuestionId
// })
// index := binarySearch(response, q.Id)
// if index != -1 {
// cell := ToAlphaString(count) + strconv.Itoa(row)
// typeMap := FileSearch(response[index].Content)
// noAccept := make(map[string]struct{})
// todoMap := make(map[string]string)
// for _, tipe := range typeMap {
// if tipe != "Text" && q.Type == model.TypeImages || q.Type == model.TypeVarImages {
// urle := ExtractImageURL(response[index].Content)
// urlData := strings.Split(urle, " ")
// for _, k := range urlData {
// u, err := url.Parse(k)
// if err == nil && u.Scheme != "" && u.Host != "" {
// picture, err := downloadImage(k)
// if err != nil {
// return err
// }
// file.SetColWidth(sheet, ToAlphaString(count), ToAlphaString(count), 50)
// file.SetRowHeight(sheet, row, 150)
// if err := file.AddPictureFromBytes(sheet, cell, picture); err != nil {
// return err
// }
// noAccept[response[index].Content] = struct{}{}
// }
// }
// } else if tipe != "Text" && q.Type == model.TypeFile {
// urle := ExtractImageURL(response[index].Content)
// display, tooltip := urle, urle
// if err := file.SetCellValue(sheet, cell, response[index].Content); err != nil {
// return err
// }
// if err := file.SetCellHyperLink(sheet, cell, urle, "External", excelize.HyperlinkOpts{
// Display: &display,
// Tooltip: &tooltip,
// }); err != nil {
// return err
// }
// noAccept[response[index].Content] = struct{}{}
// } else {
// todoMap[response[index].Content] = cell
// }
// }
// for cnt, cel := range todoMap {
// if _, ok := noAccept[cnt]; !ok {
// if err := file.SetCellValue(sheet, cel, cnt); err != nil {
// return err
// }
// }
// }
//
// } else {
// cell := ToAlphaString(count) + strconv.Itoa(row)
// if err := file.SetCellValue(sheet, cell, "-"); err != nil {
// return err
// }
// }
// count++
// }
// }
// cell := ToAlphaString(len(headers)) + strconv.Itoa(row)
// if err := file.SetCellValue(sheet, cell, mapQueRes[results[session].QuestionId]); err != nil {
// return err
// }
// row++
// }
//
// // cо х р а няе м данные в буфер
// if err := file.Write(buffer); err != nil {
// return err
// }
//
// return nil
//}