@ -1,8 +1,8 @@
/ / T O D O A d d s u b m i t b u t t o n t o l i n k w i t h f i l e u p l o a d
< template >
< form >
< input type = "file" id = "uploadInput" accept = ".xlsx" @change ="upload($event)" >
< / form >
< form >
< input type = "file" id = "uploadInput" accept = ".xlsx" @change ="fileSelected" >
< button type = "submit" @click.prevent ="parseUpload" :disabled ="!canSubmit" > Submit < / button >
< / form >
< / template >
< script >
@ -11,23 +11,23 @@ import { read, utils } from "xlsx";
import { store } from '../store.js'
import { HeaderAssociator } from '../helpers.js'
function find _header _r ow( worksheet ) {
/ / R e t u r n s t h e z e r o - i n d e x r o w n u m b e r o f t h e h e a d e r s
/ / W e w a n t t o f i n d t h e f i r s t r o w w i t h h e a d e r d a t a
/ / W e ' l l c h e c k 7 c o l u m n s o v e r ( a s t h e r e s h o u l d s t i l l b e d a t a )
/ / t h e n m a k e s u r e t h e r e a r e 3 c o n s e c u t i v e d a t a p o i n t s w i t h v a l u e s u n d e r n e a t h
for ( let row = 0 ; row < 20 ; row ++ ) {
let col = 7 ;
let address = utils . encode _cell ( { c : col , r : row } ) ;
if ( worksheet [ address ] !== undefined ) {
/ / C h e c k t h e n e x t t h r e e c e l l s a s w e l l a s t h e r o w b e l o w
let headerAdr = utils . encode _cell ( { c : col + 5 , r : row } ) ;
let headerCell = worksheet [ headerAdr ] ;
if ( headerCell !== undefined ) { return row }
function findFirstNonBlankR ow ( worksheet ) {
const range = utils . decode _range ( worksheet [ '!ref' ] ) ;
/ / W e ' l l c h e c k a t m o s t o f 2 0 r o w s
for ( let row = range . s . r ; row <= Math . min ( range . e . r , 20 ) ; row ++ ) {
var headerRow = true ;
for ( let col = 0 ; col < 20 ; col ++ ) {
const cell = worksheet [ utils . encode _cell ( { r : row , c : col } ) ] ;
if ( ! cell || cell . v === '' ) {
headerRow = false ;
break ;
}
}
if ( headerRow ) {
return row ;
}
}
return null ;
return null ;
}
@ -35,131 +35,162 @@ export default {
name : 'FileUpload' ,
data ( ) {
return {
uploadedFiles : [ ] ,
uploadError : null ,
currentStatus : null ,
uploadFieldName : 'uploadfile' ,
store
/ / U s e r u p l o a d e d f i l e
userFile : null ,
/ / H e a d e r T e m p l a t e p r o v i d e d b y s e r v e r
headerTemplateList : [ ] ,
/ / D e f i n e s w h e t h e r d a t a r o w i s c h e c k e d a g i a n s t v a l u e r e g e x
validateData : true ,
/ / S t o r e d a t a f o r a c c e s s b y o t h e r c o m p o n e n t s
store ,
/ / C o n t r o l s w h e t h e r o r n o t t h e u s e r c a n s u b m i t a f i l e
/ / - W h e n a f i l e i s s e l e c t e d , t h e n d i s a b l e d w h e n s u b m i t t e d
canSubmit : false ,
}
} ,
methods : {
async upload ( event ) {
var file = await event . target . files [ 0 ] . arrayBuffer ( ) ;
var workbook = read ( file ) ;
var worksheets = workbook . SheetNames ;
var worksheet = workbook . Sheets [ worksheets [ 0 ] ] ;
var headerIndex = find _header _row ( worksheet ) ;
/ / F I X M E : A d d h a n d l i n g f o r f a i l e d u p l o a d s a n d c h e c k i n g o t h e r s h e e t s
if ( headerIndex === null ) {
console . error ( "Failed to find valid header row" ) ;
return ;
}
/ / T O D O : T h i s s h o u l d h a p p e n o n p a g e l o a d a n d b e s t o r e d a s a p p d a t a
/ / L o a d h e a d e r / v a l u e c o n f i g
var configRequestOptions = {
async mounted ( ) {
/ / W e w a n t t o g e t t h e l a s t e s t t e m p l a t e h e a d e r s p e c i f i c a t i o n s f r o m t h e s e r v e r
try {
const configRequestOptions = {
method : 'GET' ,
redirect : 'follow' ,
} ;
var resp = await fetch ( "http://192.168.0.171:5252/api/template" , configRequestOptions ) ;
var dataStandardList = await resp . json ( ) ;
console . info ( dataStandardList ) ;
const resp = await fetch ( process . env . VUE _APP _TEMPLATE _HEADERS _ENDPOINT , configRequestOptions ) ;
let respJson = await resp . json ( ) ;
console . log ( respJson ) ;
this . headerTemplateList = respJson [ "HeaderTemplate" ] ;
/ / F I X M E : T h i s i s o n l y f o r t e s t i n g p u r p o s e s , R E M O V E T H I S
this . validateData = true ; / / r e s p J s o n [ " V a l i d a t e D a t a " ] ;
console . log ( this . headerTemplateList ) ;
console . log ( this . validateData ) ;
} catch ( error ) {
/ / F I X M E : e m i t e r r o r i n t e r n a l i s s u e s
console . error ( error ) ;
}
} ,
methods : {
/ / H e r e w e c o m p i l e a l l o f t h e h e a d e r s i n t o o n e s t r i n g
/ / T h i s w i l l l e t u s e a s i l y s e a r c h f o r e a c h h e a d e r u s i n g r e g e x
/ / T h e c o l w i l l b e n o t e d a t t h e e n d o f t h e h e a d e r s o t h a t w e c a n
/ / c h e c k t h e v a l u e
var combinedHeadersString = "" ;
console . group ( "Document columns" ) ;
for ( let col = 0 ; col < 200 ; col ++ ) {
fileSelected ( event ) {
/ / M a k e s u r e t h e u s e r c a n ' t s t i l l a c t o n t h e o l d f i l e
this . $emit ( 'parsed-upload' , null ) ;
/ / C l e a r o l d f i l e d a t a
store . missingHeaders = [ ] ;
store . documentHeaders = [ ] ;
this . userFile = event . target . files [ 0 ] ;
this . canSubmit = true ;
} ,
getHeaders ( worksheet , sheetName , headerIndex ) {
/ / S t o r e t h e f o u n d h e a d e r s
var combinedHeadersString = "" ;
/ / U s e t h e r a n g e t o m a k e s u r e w e d o n ' t g o o u t o f b o u n d s
const range = utils . decode _range ( worksheet [ '!ref' ] ) ;
for ( let col = 0 ; col < range . e . c ; col ++ ) {
let cellAddress = utils . encode _cell ( { c : col , r : headerIndex } ) ;
let cellObj = worksheet [ cellAddress ] ;
if ( cellObj === undefined ) { break }
/ / A v a l u e o f 4 0 k t y p i c a l l i n d i c a t e s a d a t e ( c a s h f l o w s )
else if ( cellObj . v > 40000 ) { break }
/ / n r e p r e s e n t s n u m b e r t y p e ( w h i c h i s p r o b a b l y t h e s t a r t o f c a s h f l o w d a t e s )
if ( cellObj === undefined || cellObj . t === 'n' ) { break }
/ / A d d t h e h e a d e r t o t h e c o m b i n e d h e a d e r s s t r i n g
combinedHeadersString += cellObj . v ;
let headerAssociator = new HeaderAssociator ( cellObj . v , cellAddress ) ;
console . info ( ` Document column: ${ headerAssociator } ` )
let headerAssociator = new HeaderAssociator ( cellObj . v , sheetName , cellAddress ) ;
if ( ! this . validateData ) { headerAssociator . isValidData = true ; }
store . documentHeaders . push ( headerAssociator ) ;
}
console . groupEnd ( ) ;
return combinedHeadersString ;
} ,
async parseUpload ( ) {
this . canSubmit = false ;
const fileBuffer = await this . userFile . arrayBuffer ( ) ;
var workbook = await read ( fileBuffer , { type : 'array' } ) ;
if ( workbook === null ) {
/ / F I X M E : E m i t b a d s p r e a d s h e e t t o a p p
console . error ( ` No workbook found! Could not parse file: ${ this . userFile . name } . ` ) ;
return ;
}
var validWorksheets = [ ]
var combinedHeadersString = '' ;
/ / G o t h r o u g h e a c h w o r k s h e e t
for ( let sheetName of workbook . SheetNames ) {
/ / O p e n t h e a c t u a l w o r k s h e e t
let worksheet = workbook . Sheets [ sheetName ] ;
/ / F i n d t h e f i r s t n o n - b l a n k r o w o f 2 0
var headerIndex = findFirstNonBlankRow ( worksheet ) ;
if ( headerIndex === null ) {
/ / P r o b a b l y n o t a s h e e t w e n e e d t o p r o c e s s
console . warn ( ` ${ sheetName } | No header row found! ` ) ;
}
/ / A d d t h e h e a d e r t o t h e c o m b i n e d h e a d e r s s t r i n g
/ / g e t H e a d e r s w i l l c r e a t e d t h e A s s o c i a t e d H e a d e r s o b j e c t s
combinedHeadersString += this . getHeaders ( worksheet , sheetName , headerIndex ) ;
/ / N o t e w h i c h w o r k s h e e t s a r e a c t u a l l y b e i n g p r o c e s s e d
validWorksheets . push ( sheetName ) ;
}
if ( validWorksheets . length === 0 ) {
/ / F I X M E : e m i t b a d s p r e a d s h e e t t o A p p
console . error ( "No worksheets found!" ) ;
return ;
}
/ / C h e c k e a c h t e m p l a t e r e g e x a g a i n s t t h e c o m b i n e d h e a d e r s s t r i n g
for ( const headerTemplate of dataStandardList ) {
console . group ( ` Header regex: ${ headerTemplate [ "Header" ] } ` ) ;
for ( const headerTemplate of this . headerTemplateList ) {
/ / ' i ' o p t i o n m e a n s i g n o r e c a s e
let headerRegex = RegExp ( headerTemplate [ "HeaderRegex" ] , "i" ) ;
let headerName = headerTemplate [ "Header" ] ;
/ / C h e c k t o s e e i f t h e t e m p l a t e h e a d e r i s p r e s e n t i n t h e c o m b i n e d h e a d e r s s t r i n g
let searchResults = headerRegex . exec ( combinedHeadersString ) ;
if ( searchResults === null ) {
console . info ( ` Header not found: ${ headerName } ` ) ;
store . missingHeaders . push ( headerName ) ;
console . groupEnd ( )
continue ;
}
let docHeader = searchResults [ 0 ] ;
console . log ( ` Match: ${ docHeader } ` ) ;
/ / N o w w e n e e d t o c h e c k t h e v a l u e b e l o w t h e h e a d e r
let isNullable = headerTemplate [ "Nullable" ] ;
/ / F i n d t h e a s s o c i a t e d h e a d e r
for ( let headerAssociator of store . documentHeaders ) {
if ( headerAssociator . isSet ( ) ) { console . groupEnd ( ) ; continue }
if ( headerAssociator . isSet ( ) ) { continue }
if ( headerAssociator . documentHeader === docHeader ) {
/ / S e t t h e a s s o c i a t e d t e m p l a t e h e a d e r
headerAssociator . swapTemplateHeader ( headerName ) ;
let headerAddress = utils . decode _cell ( headerAssociator . docHeaderAddress ) ;
/ / N o w w e c a n g e t t h e v a l u e o f t h e c e l l b e l o w t h e h e a d e r
let valueCellAddress = utils . encode _cell ( headerAddress . r + 1 ) ;
let valueObj = worksheet [ valueCellAddress ] ;
/ / C h e c k i f t h e c e l l i s n u l l , i f s o d o e s i t m a t t e r ?
if ( valueObj !== undefined ) {
/ / T e s t t h e v a l u e a g a i n s t r e g e x
let valueRegex = RegExp ( headerTemplate [ "ValueRegex" ] , 'i' ) ;
headerAssociator . isValidData = valueRegex . test ( valueObj . v ) ;
} else {
headerAssociator . isValidData = isNullable ;
if ( this . validateData ) {
/ / I f w e w a n t t o v a l i d a t e t h e d a t a , t h e n c h e c k t h e d a t a a g a i n s t t h e r e g e x
let isNullable = headerTemplate [ "Nullable" ] ;
let headerAddress = utils . decode _cell ( headerAssociator . docHeaderAddress ) ;
/ / N o w w e c a n g e t t h e v a l u e o f t h e c e l l b e l o w t h e h e a d e r
let valueCellAddress = utils . encode _cell ( headerAddress . r + 1 ) ;
/ / W e n e e d t o k n o w w h i c h w o r k s h e e t t h i s c e l l b e l o n g s t o
let worksheet = workbook . Sheets [ headerAssociator . docWorksheetName ] ;
let valueObj = worksheet [ valueCellAddress ] ;
/ / C h e c k i f t h e c e l l i s n u l l , i f s o d o e s i t m a t t e r ?
if ( valueObj !== undefined ) {
/ / T e s t t h e v a l u e a g a i n s t r e g e x
let valueRegex = RegExp ( headerTemplate [ "ValueRegex" ] , 'i' ) ;
let dataValue = valueObj . v . toString ( ) ;
let isValid = valueRegex . test ( dataValue ) ;
if ( ! isValid ) {
/ / r e c o r d t h e i n v a l i d d a t a a n d s e t i s V a l i d D a t a t o f a l s e
headerAssociator . invalidData ( dataValue ) ;
}
} else {
/ / i s V a l i d m a t c h e s i s N u l l a b l e
headerAssociator . isValidData = isNullable ;
}
}
console . info ( ` Found header: ${ headerAssociator } ` ) ;
console . groupEnd ( ) ;
/ / W e f o u n d t h e h e a d e r a n d p r o c e s s e d i t s o s t o p l o o k i n g
break ;
}
}
console . groupEnd ( ) ;
}
console . info ( ` Missing headers ( ${ store . missingHeaders . length } ): ${ store . missingHeaders } ` ) ;
console . info ( ` Document headers ( ${ store . documentHeaders . length } ): ${ store . documentHeaders } ` ) ;
/ / l e t e x c e l D o c = n e w F o r m D a t a ( ) ;
/ / e x c e l D o c . a p p e n d ( " f i l e " , e v e n t . t a r g e t . f i l e s [ 0 ] ) ;
/ / v a r r e q u e s t O p t i o n s = {
/ / m e t h o d : ' P O S T ' ,
/ / b o d y : e x c e l D o c ,
/ / r e d i r e c t : ' f o l l o w '
/ / } ;
/ / l e t r e s p = a w a i t f e t c h ( " h t t p : / / 1 9 2 . 1 6 8 . 0 . 1 7 1 : 5 2 5 2 / a p i / e x c e l u p l o a d " , r e q u e s t O p t i o n s )
/ / . t h e n ( r e s p o n s e = > r e s p o n s e . t e x t ( ) )
/ / . t h e n ( r e s u l t = > c o n s o l e . l o g ( r e s u l t ) )
/ / . c a t c h ( e r r o r = > c o n s o l e . l o g ( ' e r r o r ' , e r r o r ) ) ;
/ / c o n s o l e . l o g ( r e s p ) ;
/ / T O D O : R e m o v e l o g s
console . log ( ` Document headers ( ${ store . documentHeaders . length } ): ${ store . documentHeaders } ` ) ;
console . log ( ` Missing headers ( ${ store . missingHeaders . length } ): ${ store . missingHeaders } ` ) ;
/ / e m i t t h e u p l o a d e d f i l e & p a r s e d d a t a u p t o p a r e n t
this . $emit ( 'parsed-upload' , this . userFile ) ;
}
}
}
< / script >