Merge pull request 'fix: adjust the col numbers in extracted data' (#76) from fix-complex-xl-upload into main
Reviewed-on: #76
This commit is contained in:
commit
f13e909478
@ -186,24 +186,37 @@
|
||||
} as libdsParsed"
|
||||
class="editor-title text-center mt-0-i"
|
||||
>
|
||||
<clr-icon
|
||||
(click)="datasetInfo = true"
|
||||
shape="info-circle"
|
||||
class="is-highlight cursor-pointer"
|
||||
size="24"
|
||||
></clr-icon>
|
||||
<clr-tooltip>
|
||||
<clr-icon
|
||||
clrTooltipTrigger
|
||||
(click)="datasetInfo = true"
|
||||
shape="info-circle"
|
||||
class="is-highlight cursor-pointer"
|
||||
size="24"
|
||||
></clr-icon>
|
||||
|
||||
<clr-icon
|
||||
*ngIf="libdsParsed.tableName.includes('-FC')"
|
||||
shape="bolt"
|
||||
class="color-yellow"
|
||||
></clr-icon>
|
||||
<clr-icon
|
||||
*ngIf="libdsParsed.tableName.includes('-FC')"
|
||||
shape="bolt"
|
||||
class="color-yellow"
|
||||
></clr-icon>
|
||||
|
||||
<span clrTooltipTrigger>
|
||||
{{ libdsParsed.libName }}.<a
|
||||
class="mr-10"
|
||||
[routerLink]="'/view/data/' + libds!"
|
||||
>{{ libdsParsed.tableName.replace('-FC', '') }}</a
|
||||
>
|
||||
</span>
|
||||
<clr-tooltip-content
|
||||
clrPosition="bottom-left"
|
||||
clrSize="lg"
|
||||
*clrIfOpen
|
||||
>
|
||||
{{ this.dsNote }}
|
||||
</clr-tooltip-content>
|
||||
</clr-tooltip>
|
||||
|
||||
{{ libdsParsed.libName }}.<a
|
||||
class="mr-10"
|
||||
[routerLink]="'/view/data/' + libds!"
|
||||
>{{ libdsParsed.tableName.replace('-FC', '') }}</a
|
||||
>
|
||||
<ng-container *ngIf="dataSource">
|
||||
<ng-container *ngIf="!zeroFilterRows">
|
||||
({{ dataSource.length | thousandSeparator: ',' }}
|
||||
|
@ -121,6 +121,7 @@ export class EditorComponent implements OnInit, AfterViewInit {
|
||||
|
||||
datasetInfo: boolean = false
|
||||
dsmeta: DSMeta[] = []
|
||||
dsNote = ''
|
||||
|
||||
viewboxes: boolean = false
|
||||
|
||||
@ -2986,6 +2987,20 @@ export class EditorComponent implements OnInit, AfterViewInit {
|
||||
this.cols = response.data.cols
|
||||
this.dsmeta = response.data.dsmeta
|
||||
|
||||
const notes = this.dsmeta.find((item) => item.NAME === 'NOTES')
|
||||
const longDesc = this.dsmeta.find((item) => item.NAME === 'DD_LONGDESC')
|
||||
const shortDesc = this.dsmeta.find((item) => item.NAME === 'DD_SHORTDESC')
|
||||
|
||||
if (notes && notes.VALUE) {
|
||||
this.dsNote = notes.VALUE
|
||||
} else if (longDesc && longDesc.VALUE) {
|
||||
this.dsNote = longDesc.VALUE
|
||||
} else if (shortDesc && shortDesc.VALUE) {
|
||||
this.dsNote = shortDesc.VALUE
|
||||
} else {
|
||||
this.dsNote = ''
|
||||
}
|
||||
|
||||
const hot: Handsontable = this.hotInstance
|
||||
|
||||
const approvers: Approver[] = response.data.approvers
|
||||
|
@ -358,36 +358,49 @@
|
||||
</section>
|
||||
|
||||
<div class="title-col clr-col-auto clr-flex-column clr-flex-sm-row">
|
||||
<clr-icon
|
||||
(click)="datasetInfo = true"
|
||||
shape="info-circle"
|
||||
class="is-highlight cursor-pointer"
|
||||
size="24"
|
||||
></clr-icon>
|
||||
|
||||
<clr-icon
|
||||
*ngIf="tableTitle?.includes('-FC')"
|
||||
shape="bolt"
|
||||
class="color-yellow mt-5 mr-5"
|
||||
></clr-icon>
|
||||
|
||||
<h3
|
||||
*ngIf="tableTitle && tableTitle.length > 0"
|
||||
class="viewerTitle clr-flex-column d-flex clr-flex-sm-row clr-align-items-center"
|
||||
class="viewerTitle clr-flex-column d-flex clr-flex-sm-row clr-align-items-center clr-justify-content-center"
|
||||
>
|
||||
{{ tableTitle?.replace('-FC', '') }}
|
||||
<clr-tooltip class="d-flex">
|
||||
<clr-icon
|
||||
clrTooltipTrigger
|
||||
(click)="datasetInfo = true"
|
||||
shape="info-circle"
|
||||
class="is-highlight cursor-pointer"
|
||||
size="24"
|
||||
></clr-icon>
|
||||
|
||||
<span *ngIf="numberOfRows !== null">
|
||||
({{ numberOfRows | thousandSeparator: ',' }}
|
||||
{{ numberOfRows! === 1 ? 'row' : 'rows' }}, {{ filterCols.length
|
||||
}}{{ filterCols.length === 1 ? ' col' : ' cols' }})
|
||||
</span>
|
||||
<clr-icon
|
||||
*ngIf="tableTitle?.includes('-FC')"
|
||||
shape="bolt"
|
||||
class="color-yellow mt-5 mr-5"
|
||||
></clr-icon>
|
||||
|
||||
<clr-icon
|
||||
(click)="reloadTableData()"
|
||||
class="refresh-table"
|
||||
shape="refresh"
|
||||
></clr-icon>
|
||||
<span clrTooltipTrigger *ngIf="tableTitle && tableTitle.length > 0">
|
||||
{{ tableTitle?.replace('-FC', '') }}
|
||||
</span>
|
||||
<clr-tooltip-content
|
||||
clrPosition="bottom-left"
|
||||
clrSize="lg"
|
||||
*clrIfOpen
|
||||
>
|
||||
{{ this.dsNote }}
|
||||
</clr-tooltip-content>
|
||||
</clr-tooltip>
|
||||
|
||||
<ng-container *ngIf="tableTitle && tableTitle.length > 0">
|
||||
<span *ngIf="numberOfRows !== null">
|
||||
({{ numberOfRows | thousandSeparator: ',' }}
|
||||
{{ numberOfRows! === 1 ? 'row' : 'rows' }}, {{ filterCols.length
|
||||
}}{{ filterCols.length === 1 ? ' col' : ' cols' }})
|
||||
</span>
|
||||
|
||||
<clr-icon
|
||||
(click)="reloadTableData()"
|
||||
class="refresh-table"
|
||||
shape="refresh"
|
||||
></clr-icon>
|
||||
</ng-container>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
|
@ -95,6 +95,7 @@ export class ViewerComponent implements AfterContentInit, AfterViewInit {
|
||||
public $dataFormats: $DataFormats | null = null
|
||||
public datasetInfo: boolean = false
|
||||
public dsmeta: DSMeta[] = []
|
||||
public dsNote = ''
|
||||
|
||||
public licenceState = this.licenceService.licenceState
|
||||
public Infinity = Infinity
|
||||
@ -246,6 +247,7 @@ export class ViewerComponent implements AfterContentInit, AfterViewInit {
|
||||
this.hotTable.data = res.viewdata
|
||||
this.$dataFormats = res.$viewdata
|
||||
this.dsmeta = res.dsmeta
|
||||
this.setDSNote()
|
||||
this.numberOfRows = res.sasparams[0].NOBS
|
||||
this.queryText = res.sasparams[0].FILTER_TEXT
|
||||
this.headerPks = res.sasparams[0].PK_FIELDS.split(' ')
|
||||
@ -803,6 +805,7 @@ export class ViewerComponent implements AfterContentInit, AfterViewInit {
|
||||
this.hotTable.data = res.viewdata
|
||||
this.$dataFormats = res.$viewdata
|
||||
this.dsmeta = res.dsmeta
|
||||
this.setDSNote()
|
||||
this.queryText = res.sasparams[0].FILTER_TEXT
|
||||
let columns: any[] = []
|
||||
let colArr = []
|
||||
@ -1016,6 +1019,22 @@ export class ViewerComponent implements AfterContentInit, AfterViewInit {
|
||||
this.sasStoreService.removeClause()
|
||||
}
|
||||
|
||||
private setDSNote() {
|
||||
const notes = this.dsmeta.find((item) => item.NAME === 'NOTES')
|
||||
const longDesc = this.dsmeta.find((item) => item.NAME === 'DD_LONGDESC')
|
||||
const shortDesc = this.dsmeta.find((item) => item.NAME === 'DD_SHORTDESC')
|
||||
|
||||
if (notes && notes.VALUE) {
|
||||
this.dsNote = notes.VALUE
|
||||
} else if (longDesc && longDesc.VALUE) {
|
||||
this.dsNote = longDesc.VALUE
|
||||
} else if (shortDesc && shortDesc.VALUE) {
|
||||
this.dsNote = shortDesc.VALUE
|
||||
} else {
|
||||
this.dsNote = ''
|
||||
}
|
||||
}
|
||||
|
||||
private setupHot() {
|
||||
setTimeout(() => {
|
||||
if (!this.loadingTableView && this.libDataset) {
|
||||
|
@ -385,34 +385,39 @@ export class XLMapComponent implements AfterContentInit, AfterViewInit, OnInit {
|
||||
const start = getCellAddress(rule.XLMAP_START, arrayOfObjects)
|
||||
const finish = getFinishingCell(start, rule.XLMAP_FINISH, arrayOfObjects)
|
||||
|
||||
const range = `${start}:${finish}`
|
||||
const a1Range = `${start}:${finish}`
|
||||
|
||||
const range = XLSX.utils.decode_range(a1Range)
|
||||
|
||||
const rangedData = <any[]>XLSX.utils.sheet_to_json(sheet, {
|
||||
raw: true,
|
||||
range: range,
|
||||
range: a1Range,
|
||||
header: 'A',
|
||||
blankrows: true
|
||||
})
|
||||
|
||||
for (let i = 0; i < rangedData.length; i++) {
|
||||
const row = rangedData[i]
|
||||
// Get the keys of the object (excluding '__rowNum__')
|
||||
const keys = Object.keys(row).filter((key) => key !== '__rowNum__')
|
||||
|
||||
for (let j = 0; j < keys.length; j++) {
|
||||
const key = keys[j]
|
||||
const val = row[key]
|
||||
// `range.s.c` is the index of first column in the range
|
||||
// `range.e.c` is the index of last column in the range
|
||||
// we'll iterate from first column to last column and
|
||||
// extract value where defined and push to extracted data array
|
||||
for (let j = range.s.c, x = 0; j <= range.e.c; j++, x++) {
|
||||
const col = XLSX.utils.encode_col(j)
|
||||
|
||||
// in excel's R1C1 notation indexing starts from 1 but in JS it starts from 0
|
||||
// therefore, we'll have to add 1 to rows and cols
|
||||
extractedData.push({
|
||||
LOAD_REF: '0',
|
||||
XLMAP_ID: rule.XLMAP_ID,
|
||||
XLMAP_RANGE_ID: rule.XLMAP_RANGE_ID,
|
||||
ROW_NO: i + 1,
|
||||
COL_NO: j + 1,
|
||||
VALUE_TXT: val
|
||||
})
|
||||
if (col in row) {
|
||||
// in excel's R1C1 notation indexing starts from 1 but in JS it starts from 0
|
||||
// therefore, we'll have to add 1 to rows and cols
|
||||
extractedData.push({
|
||||
LOAD_REF: '0',
|
||||
XLMAP_ID: rule.XLMAP_ID,
|
||||
XLMAP_RANGE_ID: rule.XLMAP_RANGE_ID,
|
||||
ROW_NO: i + 1,
|
||||
COL_NO: x + 1,
|
||||
VALUE_TXT: row[col]
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -18,4 +18,4 @@ In any case, you must not make any such use of this software as to develop softw
|
||||
UNLESS EXPRESSLY AGREED OTHERWISE, 4GL APPS PROVIDES THIS SOFTWARE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, AND IN NO EVENT AND UNDER NO LEGAL THEORY, SHALL 4GL APPS BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER ARISING FROM USE OR INABILITY TO USE THIS SOFTWARE.
|
||||
|
||||
|
||||
`
|
||||
`
|
||||
|
70
sas/sasjs/macros/mpe_dsmeta.sas
Normal file
70
sas/sasjs/macros/mpe_dsmeta.sas
Normal file
@ -0,0 +1,70 @@
|
||||
/**
|
||||
@file
|
||||
@brief Gets table metadata
|
||||
@details Runs mp_dsmeta and adds datadictionary info
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mp_dsmeta.sas
|
||||
|
||||
@version 9.2
|
||||
@author 4GL Apps Ltd
|
||||
@copyright 4GL Apps Ltd. This code may only be used within Data Controller
|
||||
and may not be re-distributed or re-sold without the express permission of
|
||||
4GL Apps Ltd.
|
||||
**/
|
||||
|
||||
%macro mpe_dsmeta(libds, outds=dsmeta);
|
||||
%local ddsd ddld notes lenstmt;
|
||||
%let lenstmt=length ods_table $18 name $100 value $1000;
|
||||
%let libds=%upcase(&libds);
|
||||
%mp_dsmeta(&libds, outds=&outds)
|
||||
|
||||
data _null_;
|
||||
set &mpelib..mpe_datadictionary;
|
||||
where &dc_dttmtfmt < tx_to & dd_source=%upcase("&libds") & dd_type='TABLE';
|
||||
call symputx('ddsd',dd_shortdesc,'l');
|
||||
call symputx('ddld',dd_longdesc,'l');
|
||||
run;
|
||||
|
||||
data &outds;
|
||||
&lenstmt;
|
||||
if last then do;
|
||||
ODS_TABLE='MPE_DATADICTIONARY';
|
||||
NAME='DD_SHORTDESC';
|
||||
VALUE="&ddsd";
|
||||
output;
|
||||
NAME='DD_LONGDESC';
|
||||
VALUE="&ddld";
|
||||
output;
|
||||
end;
|
||||
set &outds end=last;
|
||||
output;
|
||||
run;
|
||||
|
||||
data _data_;
|
||||
set &mpelib..mpe_tables;
|
||||
where libref="%scan(&libds,1,.)"
|
||||
& dsn="%scan(&libds,2,.)"
|
||||
& &dc_dttmtfmt<tx_to;
|
||||
&lenstmt;
|
||||
ODS_TABLE='MPE_TABLES';
|
||||
array c _character_;
|
||||
array n _numeric_;
|
||||
do over c;
|
||||
name=upcase(vname(c));
|
||||
value=c;
|
||||
output;
|
||||
end;
|
||||
do over n;
|
||||
name=upcase(vname(n));
|
||||
value=cats(n);
|
||||
output;
|
||||
end;
|
||||
keep ods_table name value;
|
||||
run;
|
||||
|
||||
proc append base=&outds data=&syslast;
|
||||
run;
|
||||
|
||||
|
||||
%mend mpe_dsmeta;
|
37
sas/sasjs/macros/mpe_dsmeta.test.sas
Normal file
37
sas/sasjs/macros/mpe_dsmeta.test.sas
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
@file
|
||||
@brief Testing mpe_dsmeta macro
|
||||
@details Checking functionality of mpe_dsmeta.sas macro
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mp_assertdsobs.sas
|
||||
@li mp_assertscope.sas
|
||||
@li mpe_dsmeta.sas
|
||||
|
||||
@author 4GL Apps Ltd
|
||||
@copyright 4GL Apps Ltd. This code may only be used within Data Controller
|
||||
and may not be re-distributed or re-sold without the express permission of
|
||||
4GL Apps Ltd.
|
||||
|
||||
**/
|
||||
|
||||
/* run the macro*/
|
||||
%mp_assertscope(SNAPSHOT)
|
||||
%mpe_dsmeta(&mpelib..mpe_security, outds=test1)
|
||||
%mp_assertscope(COMPARE,
|
||||
desc=Checking macro variables against previous snapshot
|
||||
)
|
||||
|
||||
data work.test1;
|
||||
set work.test1;
|
||||
where ods_table in ('MPE_DATADICTIONARY','MPE_TABLES');
|
||||
putlog (_all_)(=);
|
||||
run;
|
||||
|
||||
%mp_assertdsobs(work.test1,
|
||||
desc=Test 1 - 27 records returned,
|
||||
test=EQUALS 27,
|
||||
outds=work.test_results
|
||||
)
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
<h5> sasdata </h5>
|
||||
<h5> sasparams </h5>
|
||||
Contains info on the request. One row is returned.
|
||||
@li CLS_FLG - set to 0 if there are no CLS rules (everything should be editable)
|
||||
@li CLS_FLG - set to 0 if there are no CLS rules (everything editable)
|
||||
else set to 1 (CLS rules exist)
|
||||
@li ISMAP - set to 1 if the target DS is an excel map target, else 0
|
||||
|
||||
@ -56,12 +56,12 @@
|
||||
@li mf_wordsinstr1butnotstr2.sas
|
||||
@li mp_abort.sas
|
||||
@li mp_cntlout.sas
|
||||
@li mp_dsmeta.sas
|
||||
@li mp_getcols.sas
|
||||
@li mp_getmaxvarlengths.sas
|
||||
@li mp_validatecol.sas
|
||||
@li mpe_accesscheck.sas
|
||||
@li mpe_columnlevelsecurity.sas
|
||||
@li mpe_dsmeta.sas
|
||||
@li mpe_getlabels.sas
|
||||
@li mpe_filtermaster.sas
|
||||
@li mpe_runhook.sas
|
||||
@ -665,7 +665,7 @@ data xl_rules;
|
||||
keep xl_column xl_rule;
|
||||
run;
|
||||
|
||||
%mp_dsmeta(&libds, outds=dsmeta)
|
||||
%mpe_dsmeta(&libds, outds=dsmeta)
|
||||
|
||||
/* send to the client */
|
||||
%webout(OPEN)
|
||||
|
@ -21,7 +21,7 @@
|
||||
data _null_;
|
||||
file &f1 termstr=crlf;
|
||||
put 'XLMAP_ID:$char12.';
|
||||
put "Sample";
|
||||
put "BASEL-KM1";
|
||||
run;
|
||||
|
||||
%mx_testservice(&_program,
|
||||
@ -38,7 +38,7 @@ run;
|
||||
|
||||
%mp_assertdsobs(work.xlmaprules,
|
||||
test=ATLEAST 2,
|
||||
desc=Checking successful return of at least 2 rules for the Sample map,
|
||||
desc=Checking successful return of at least 2 rules for the BASEL-KM1 map,
|
||||
outds=work.test_results
|
||||
)
|
||||
|
||||
|
@ -44,13 +44,13 @@
|
||||
@li mf_verifymacvars.sas
|
||||
@li mp_abort.sas
|
||||
@li mp_cntlout.sas
|
||||
@li mp_dsmeta.sas
|
||||
@li mp_getcols.sas
|
||||
@li mp_getpk.sas
|
||||
@li mp_jsonout.sas
|
||||
@li mp_searchdata.sas
|
||||
@li mp_validatecol.sas
|
||||
@li mpe_columnlevelsecurity.sas
|
||||
@li mpe_dsmeta.sas
|
||||
@li mpe_filtermaster.sas
|
||||
|
||||
|
||||
@ -351,7 +351,7 @@ run;
|
||||
|
||||
%mp_getcols(&libds, outds=cols)
|
||||
|
||||
%mp_dsmeta(&libds, outds=dsmeta)
|
||||
%mpe_dsmeta(&libds, outds=dsmeta)
|
||||
|
||||
%webout(OPEN)
|
||||
%webout(OBJ,cls_rules)
|
||||
|
Loading…
Reference in New Issue
Block a user