├── 3.Include ├── 4.Sub │ ├── 10.QVDLoad.qvs │ ├── Info.txt │ ├── 13.NiceTrace.qvs │ ├── 1.FileExist.qvs │ ├── 14.QVDReduce.qvs │ ├── 99.LoadAll.qvs │ ├── 6.CreateFolder.qvs │ ├── README.md │ ├── 15.ETLLog.qvs │ ├── 5.DoDir.qvs │ ├── 4.GenericContainerLoader.qvs │ ├── 11.DynamicContainerLoader.qvs │ ├── 3.LoadContainerMap.qvs │ ├── 8.QVFileInfo.qvs │ ├── 9.QVDMigration.qvs │ ├── 2.LoadVariableCSV.qvs │ ├── 7.CalendarGen.qvs │ └── 12.Index.qvs ├── 2.Locale │ ├── 2.Swe.qvs │ ├── 4.Fra.qvs │ ├── 5.Spa.qvs │ ├── 6.Ita.qvs │ ├── 7.Por.qvs │ ├── 9.Jap.qvs │ ├── 1.US.qvs │ ├── 10.Ger.qvs │ ├── 11.Aus.qvs │ ├── 3.UK.qvs │ ├── 8.Rus.qvs │ ├── Info.txt │ ├── 12.Bra.qvs │ └── 13.Fin.qvs ├── Info.txt └── 1.BaseVariable │ ├── Info.txt │ ├── 4.Custom.qvs │ ├── 3.SystemVariables.qvs │ └── 1.Init.qvs ├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── InitLinkSkip.qvs ├── InitLink.qvs └── Version1.7.5.txt /3.Include/4.Sub/10.QVDLoad.qvs: -------------------------------------------------------------------------------- 1 | // Function merged together with 9.QVDmigration.qvs -------------------------------------------------------------------------------- /3.Include/2.Locale/2.Swe.qvs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QlikDeploymentFramework/Qlik-Deployment-Framework/HEAD/3.Include/2.Locale/2.Swe.qvs -------------------------------------------------------------------------------- /3.Include/2.Locale/4.Fra.qvs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QlikDeploymentFramework/Qlik-Deployment-Framework/HEAD/3.Include/2.Locale/4.Fra.qvs -------------------------------------------------------------------------------- /3.Include/2.Locale/5.Spa.qvs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QlikDeploymentFramework/Qlik-Deployment-Framework/HEAD/3.Include/2.Locale/5.Spa.qvs -------------------------------------------------------------------------------- /3.Include/2.Locale/6.Ita.qvs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QlikDeploymentFramework/Qlik-Deployment-Framework/HEAD/3.Include/2.Locale/6.Ita.qvs -------------------------------------------------------------------------------- /3.Include/2.Locale/7.Por.qvs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QlikDeploymentFramework/Qlik-Deployment-Framework/HEAD/3.Include/2.Locale/7.Por.qvs -------------------------------------------------------------------------------- /3.Include/2.Locale/9.Jap.qvs: -------------------------------------------------------------------------------- 1 | ///$tab Main 2 | SET ThousandSep=','; 3 | SET DecimalSep='.'; 4 | SET MoneyThousandSep=','; 5 | SET MoneyDecimalSep='.'; 6 | SET MoneyFormat='¥#,##0;-¥#,##0'; 7 | SET TimeFormat='h:mm:ss'; 8 | SET DateFormat='YYYY/MM/DD'; 9 | SET TimestampFormat='YYYY/MM/DD h:mm:ss[.fff]'; 10 | SET MonthNames='1;2;3;4;5;6;7;8;9;10;11;12'; 11 | SET DayNames='月;火;水;木;金;土;日'; 12 | 13 | -------------------------------------------------------------------------------- /3.Include/2.Locale/1.US.qvs: -------------------------------------------------------------------------------- 1 | SET ThousandSep=','; 2 | SET DecimalSep='.'; 3 | SET MoneyThousandSep=','; 4 | SET MoneyDecimalSep='.'; 5 | SET MoneyFormat='$#,##0.00;($#,##0.00)'; 6 | SET TimeFormat='h:mm:ss TT'; 7 | SET DateFormat='M/D/YYYY'; 8 | SET TimestampFormat='M/D/YYYY h:mm:ss[.fff] TT'; 9 | SET MonthNames='Jan;Feb;Mar;Apr;May;Jun;Jul;Aug;Sep;Oct;Nov;Dec'; 10 | SET DayNames='Mon;Tue;Wed;Thu;Fri;Sat;Sun'; -------------------------------------------------------------------------------- /3.Include/2.Locale/10.Ger.qvs: -------------------------------------------------------------------------------- 1 | SET ThousandSep='.'; 2 | SET DecimalSep=','; 3 | SET MoneyThousandSep='.'; 4 | SET MoneyDecimalSep=','; 5 | SET MoneyFormat='#.##0,00 €;-#.##0,00 €'; 6 | SET TimeFormat='hh:mm:ss'; 7 | SET DateFormat='DD.MM.YYYY'; 8 | SET TimestampFormat='DD.MM.YYYY hh:mm:ss[.fff]'; 9 | SET MonthNames='Jan;Feb;Mrz;Apr;Mai;Jun;Jul;Aug;Sep;Okt;Nov;Dez'; 10 | SET DayNames='Mo;Di;Mi;Do;Fr;Sa;So'; 11 | 12 | -------------------------------------------------------------------------------- /3.Include/2.Locale/11.Aus.qvs: -------------------------------------------------------------------------------- 1 | SET ThousandSep=','; 2 | SET DecimalSep='.'; 3 | SET MoneyThousandSep=','; 4 | SET MoneyDecimalSep='.'; 5 | SET MoneyFormat='$#,##0.00;($#,##0.00)'; 6 | SET TimeFormat='h:mm:ss TT'; 7 | SET DateFormat='DD/MM/YYYY'; 8 | SET TimestampFormat='DD/MM/YYYY h:mm:ss[.fff] TT'; 9 | SET MonthNames='Jan;Feb;Mar;Apr;May;Jun;Jul;Aug;Sep;Oct;Nov;Dec'; 10 | SET DayNames='Mon;Tue;Wed;Thu;Fri;Sat;Sun'; -------------------------------------------------------------------------------- /3.Include/2.Locale/3.UK.qvs: -------------------------------------------------------------------------------- 1 | SET ThousandSep =','; 2 | SET DecimalSep='.'; 3 | SET MoneyThousandSep=','; 4 | SET MoneyDecimalSep='.'; 5 | SET MoneyFormat='£#,##0.00;-£#,##0.00'; 6 | SET TimeFormat='hh:mm:ss'; 7 | SET DateFormat='DD/MM/YYYY'; 8 | SET TimestampFormat='DD/MM/YYYY hh:mm:ss[.fff]'; 9 | SET MonthNames='Jan;Feb;Mar;Apr;May;Jun;Jul;Aug;Sep;Oct;Nov;Dec'; 10 | SET DayNames='Mon;Tue;Wed;Thu;Fri;Sat;Sun'; 11 | 12 | -------------------------------------------------------------------------------- /3.Include/2.Locale/8.Rus.qvs: -------------------------------------------------------------------------------- 1 | ///$tab Main 2 | SET ThousandSep=' '; 3 | SET DecimalSep=','; 4 | SET MoneyThousandSep=' '; 5 | SET MoneyDecimalSep=','; 6 | SET MoneyFormat='# ##0,00р.;-# ##0,00р.'; 7 | SET TimeFormat='h:mm:ss'; 8 | SET DateFormat='DD.MM.YYYY'; 9 | SET TimestampFormat='DD.MM.YYYY h:mm:ss[.fff]'; 10 | SET MonthNames='янв;фев;мар;апр;май;июн;июл;авг;сен;окт;ноя;дек'; 11 | SET DayNames='Пн;Вт;Ср;Чт;Пт;Сб;Вс'; 12 | 13 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /3.Include/Info.txt: -------------------------------------------------------------------------------- 1 | // ____________________________________________________________ 2 | // | Deployment Framework Path Info txt | 3 | // | Contains information folder purpose and base variable | 4 | // | All path are based on vG.BasePath | 5 | // |___________________________________________________________| 6 | 7 | // IncludePath points to 3.Include base folder, all Qlik include scripts are stored here 8 | 9 | Global Variable = vG.IncludePath 10 | Shared Global Variable= vG.SharedIncludePath -------------------------------------------------------------------------------- /3.Include/2.Locale/Info.txt: -------------------------------------------------------------------------------- 1 | // ____________________________________________________________ 2 | // | Deployment Framework Path Info txt | 3 | // | Contains information folder purpose and base variable | 4 | // | All path are based on vG.LocalePath | 5 | // |___________________________________________________________| 6 | 7 | // vG.IncludePath points to 3.Include\2.Locale folder 8 | 9 | // Store for language specific settings 10 | // Example: $(Include=$(vG.LocalePath)\1.US.qvs); 11 | 12 | Global Variable = vG.IncludePath 13 | Shared Global Variable= vG.SharedIncludePath -------------------------------------------------------------------------------- /3.Include/2.Locale/12.Bra.qvs: -------------------------------------------------------------------------------- 1 | // Brazil settings 2 | SET ThousandSep='.'; 3 | SET DecimalSep=','; 4 | SET MoneyThousandSep='.'; 5 | SET MoneyDecimalSep=','; 6 | SET MoneyFormat='R$ #.##0,00;(R$ #.##0,00)'; 7 | SET TimeFormat='hh:mm:ss'; 8 | SET DateFormat='DD/MM/YYYY'; 9 | SET TimestampFormat='DD/MM/YYYY hh:mm:ss[.fff]'; 10 | SET MonthNames='Jan;Fev;Mar;Abr;Mai;Jun;Jul;Ago;Set;Out;Nov;Dez'; 11 | SET DayNames='Seg;Ter;Qua;Qui;Sex;Sab;Dom'; 12 | SET LongMonthNames='Janeiro;Fevereiro;Março;Abril;Maio;Junho;Julho;Agosto;Setembro;Outubro;Novembro;Dezembro'; 13 | SET LongDayNames='Segunda;Terça;Quarta;Quinta;Sexta;Sábado;Domingo'; 14 | 15 | -------------------------------------------------------------------------------- /3.Include/4.Sub/Info.txt: -------------------------------------------------------------------------------- 1 | // ____________________________________________________________ 2 | // | Deployment Framework Path Info txt | 3 | // | Contains information folder purpose and base variable | 4 | // | All path are based on vG.BasePath | 5 | // |___________________________________________________________| 6 | 7 | // vG.SubPath points to 3.Include\4.Sub path 8 | 9 | // Sub include scripts are stored here = $(vG.SubPath) 10 | // Use call inside QlikView Script to execute a sub, example: 11 | // CALL LoadVariableCSV('Custom.Variables.csv'); 12 | 13 | Global Variable = vG.SubPath 14 | Shared Global Variable= vG.SharedSubPath -------------------------------------------------------------------------------- /3.Include/1.BaseVariable/Info.txt: -------------------------------------------------------------------------------- 1 | // ____________________________________________________________ 2 | // | Deployment Framework Path Info txt | 3 | // | Contains information folder purpose and base variable | 4 | // | All path are based on vG.BasePath | 5 | // |___________________________________________________________| 6 | 7 | // vG.BaseVariable points to 1.BaseVariable folder 8 | // This folder contains 1.Init.qvs Include scripts to initiate Deployment framework in the qvw or qvf 9 | // the first Include should always be 1.Init.qvs 10 | // Example: $(Include=..\..\..\3.include\1.basevariable\1.init.qvs); 11 | 12 | Global Variable = vG.BaseVariablePath 13 | Shared Global Variable= vG.SharedBaseVariablePath -------------------------------------------------------------------------------- /3.Include/4.Sub/13.NiceTrace.qvs: -------------------------------------------------------------------------------- 1 | // This Sub enables prettified output of text to the reload progress window of Qlik Sense. 2 | // Use it to get timestamped trace messages, that also have a prefix that makes them easier 3 | // to spot in the reload progress windows and reload logs. 4 | // 5 | // Usage example: 6 | // call vL.NiceTrace ('This is a debug message, including a variable $(vL.MetaDataQVDPath)\SOE.QVD') 7 | 8 | 9 | 10 | sub vL.NiceTrace (vL.QDF.Msg) 11 | 12 | let vL.vNow = Now(1); 13 | trace >>> $(vL.vNow): $(vL.QDF.Msg); 14 | 15 | // Remove local variables before exiting 16 | set vL.vNow=; 17 | set vL.QDF.Msg=; 18 | 19 | end sub; 20 | 21 | 22 | // ********************************** 23 | // Function written by Göran Sander 24 | // ********************************** -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | *.qvd 17 | *.qvf 18 | *.qvw 19 | *.log 20 | *.index 21 | 22 | # Windows shortcuts 23 | *.lnk 24 | 25 | # ========================= 26 | # Operating System Files 27 | # ========================= 28 | 29 | # OSX 30 | # ========================= 31 | 32 | .DS_Store 33 | .AppleDouble 34 | .LSOverride 35 | 36 | # Thumbnails 37 | ._* 38 | 39 | # Files that might appear in the root of a volume 40 | .DocumentRevisions-V100 41 | .fseventsd 42 | .Spotlight-V100 43 | .TemporaryItems 44 | .Trashes 45 | .VolumeIcon.icns 46 | 47 | # Directories potentially created on remote AFP share 48 | .AppleDB 49 | .AppleDesktop 50 | Network Trash Folder 51 | Temporary Items 52 | .apdisk 53 | -------------------------------------------------------------------------------- /3.Include/2.Locale/13.Fin.qvs: -------------------------------------------------------------------------------- 1 | SET ThousandSep=' '; 2 | SET DecimalSep=','; 3 | SET MoneyThousandSep=' '; 4 | SET MoneyDecimalSep=','; 5 | SET MoneyFormat='# ##0,00 €;-# ##0,00 €'; 6 | SET TimeFormat='h.mm.ss'; 7 | SET DateFormat='D.M.YYYY'; 8 | SET TimestampFormat='D.M.YYYY h.mm.ss[.fff]'; 9 | SET FirstWeekDay=0; 10 | SET BrokenWeeks=0; 11 | SET ReferenceDay=4; 12 | SET FirstMonthOfYear=1; 13 | SET CollationLocale='fi-FI'; 14 | SET CreateSearchIndexOnReload=1; 15 | SET MonthNames='tammik.;helmik.;maalisk.;huhtik.;toukok.;kesäk.;heinäk.;elok.;syysk.;lokak.;marrask.;jouluk.'; 16 | SET LongMonthNames='tammikuu;helmikuu;maaliskuu;huhtikuu;toukokuu;kesäkuu;heinäkuu;elokuu;syyskuu;lokakuu;marraskuu;joulukuu'; 17 | SET DayNames='ma;ti;ke;to;pe;la;su'; 18 | SET LongDayNames='maanantaina;tiistaina;keskiviikkona;torstaina;perjantaina;lauantaina;sunnuntaina'; 19 | SET NumericalAbbreviation='3:k;6:M;9:G;12:T;15:P;18:E;21:Z;24:Y;-3:m;-6:μ;-9:n;-12:p;-15:f;-18:a;-21:z;-24:y'; 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Qlik 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /3.Include/1.BaseVariable/4.Custom.qvs: -------------------------------------------------------------------------------- 1 | ; 2 | //____________________________________________________________ 3 | // Qlik Deployment Framework BaseVariable 4.Custom.qvs 4 | // This Include contains Custom path like QVD Sub folders 5 | // If possible path should be based on Variables created 6 | // by the framework like $(vG.QVDPath) and $(vG.BasePath) 7 | // Used to add custom Global Variables (vG.) 8 | // Recommendation is to use Deployment Framework Global Variable Editor (VariableEditor.qvw) instead of this file 9 | //___________________________________________________________*/ 10 | 11 | 12 | // trace '### QDF Info, executing 4.Custom.qvs'; // Uncomment to Write information log 13 | 14 | 15 | 16 | // This example will create global variables for the additional folders 1.Extract 2.Transform 3.Load 17 | // Call DCGV('','Extract;Transform;Load'); 18 | // The function will be executed by Qlik apps if the modified 4.custom.qvs is stored in shared container 19 | // The function will be executed by all Qlik apps in the container that stores the modified 4.custom.qvs 20 | 21 | 22 | 23 | 24 | // Uncomment to Write information log 25 | // trace '### QDF Info, 4.Custom.qvs Finished'; -------------------------------------------------------------------------------- /3.Include/4.Sub/1.FileExist.qvs: -------------------------------------------------------------------------------- 1 | // ___________________________________________________________________________ 2 | // Qlik Deployment FrameworkvL.FileExist sub function 1.FileExist 3 | // This Sub will check if a file or folder exists 4 | // Use before load to avoid errors during script load 5 | // Syntax example in the script: 6 | // call vL.FileExist ('$(vL.MetaDataQVDPath)\SOE.QVD') 7 | // Local Variable vL.FileExist returns false or true 8 | // example usage: 9 | // if vL.FileExist = 'false' then; trace '### DF Did not find file, exit script'; exit script; endif; 10 | 11 | sub vL.FileExist (vL.QDF.Root) 12 | 13 | // Remove backslash in end 14 | do while right( '$(vL.QDF.Root)' , 1 ) ='\' 15 | let vL.QDF.Root =left('$(vL.QDF.Root)', Len('$(vL.QDF.Root)')-1); 16 | exit do unless right( '$(vL.QDF.Root)' , 1 ) ='\'; 17 | loop 18 | 19 | if IsNull(filesize('$(vL.QDF.Root)')) = -1 then 20 | SET vL.FileExist='false'; 21 | else 22 | SET vL.FileExist='true'; 23 | endif 24 | set vL.QDF.Root=; 25 | end sub; 26 | 27 | 28 | // ********************************** 29 | // Function written by Frederik N�nning and Magnus Berg 30 | // QlikTech GmbH 31 | // QlikTech International 32 | // ********************************** -------------------------------------------------------------------------------- /3.Include/4.Sub/14.QVDReduce.qvs: -------------------------------------------------------------------------------- 1 | // ___________________________________________________________________________ 2 | // Deployment Framework QVDReduce sub function 14.QVDReduce.qvs 3 | // 4 | // As part of ETL process it is often required to create temporary QVD files. 5 | // These files often result in a more efficient (faster) processing time, rather 6 | // than the alternative leveraging Resident load. 7 | // 8 | // Qlik Sense does not support the ability to delete files from the operating system. 9 | // This sub-routine provides the ability to reduce the size of these temporary QVD files. 10 | // Therefore ensuring that disk space is not consumed by temporary files. 11 | // 12 | // Use the function QVDReduce to execute. examples: 13 | // Call reduceQVD('$(vL.QVDStagePath)','stageIVRData2.QVD'); 14 | 15 | SUB reduceQVD (vL.QDF.Path, vL.QDF.File) 16 | // Trace $(vL.QDF.Path); 17 | // Trace $(vL.QDF.File); 18 | 19 | NoConcatenate 20 | $(vL.QDF.File): 21 | LOAD * Inline [ 22 | EMPTY 23 | ]; 24 | 25 | STORE $(vL.QDF.File) into [$(vL.QDF.Path)$(vL.QDF.File)]; 26 | DROP Table $(vL.QDF.File); 27 | 28 | SET vL.QDF.Path=; 29 | SET vL.QDF.File=; 30 | 31 | END SUB; 32 | 33 | // **************************************** 34 | // Functions written by Damian Waldron Qlik 35 | // **************************************** -------------------------------------------------------------------------------- /3.Include/1.BaseVariable/3.SystemVariables.qvs: -------------------------------------------------------------------------------- 1 | // ____________________________________________________________ 2 | // Deployment Framework BaseVariable 3.SystemVariables.qvs 3 | // This Include contains system folder path for QLikView event logs, 4 | // QLikView Publisher database and custom data source logs 5 | // ___________________________________________________________ 6 | // Writing information in log 7 | trace '### DF 3.SystemVariables.qvs Started'; 8 | 9 | $(Include=$(vG.SubPath)\2.LoadVariableCSV.qvs); 10 | 11 | // Loading include file containing the CSV sub function LoadVariableCSV 12 | $(Include=$(vG.SubPath)\1.FileExist.qvs); 13 | call vL.FileExist ('$(vG.BaseVariablePath)\System*'); 14 | 15 | if vL.FileExist = 'false' then 16 | call LoadContainerGlobalVariables('Admin','BaseVariable'); 17 | call vL.FileExist ('$(vG.AdminBaseVariablePath)\System*'); 18 | if vL.FileExist = 'true' then 19 | call LCGV('Admin','BaseVariable'); 20 | call LoadVariableCSV('$(vG.AdminBaseVariablePath)\System*.csv'); 21 | else 22 | trace '### DF Error 3.SystemVariables.qvs have no access to $(vG.AdminBaseVariablePath)\System.Variables.csv'; 23 | endif 24 | else 25 | call LoadVariableCSV('$(vG.BaseVariablePath)\System*.csv'); 26 | endif 27 | 28 | SET vL.FileExist=; 29 | // Writing information in log 30 | trace '### DF 3.SystemVariables.qvs Finished'; 31 | 32 | 33 | 34 | // ********************************** 35 | // 3.SystemVariables.qvs written by Magnus Berg 36 | // QlikTech International AB 37 | // ********************************** -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Qlik-Deployment-Framework (QDF) 2 | **QDF version 1.7.5** 3 | 4 | ## QDF is a set of Qlik scripts and utilities that enables: 5 | Resource Sharing, Reuse, Organization, Structure and Standards providing an effective and efficient Qlik deployment. 6 | Qlik-Deployment-Framework content is available at https://community.qlik.com/groups/qlikview-deployment-framework 7 | 8 | ## Qlik Deployment Framework resource containers 9 | QDF is based on a resource container architecture. Arrange containers (building blocks and security separators) to fit the current needs, when demand changes its easy to reorganize and add additional containers. QlikView and/or Qlik Sense applications are hooked into the containers in which all needed resources reside. 10 | 11 | ## Qlik Deployment Framework Deploy Tool binary releases 12 | Available under releases tab: https://github.com/QlikDeploymentFramework/Qlik-Deployment-Framework/releases 13 | 14 | ## Qlik-Deployment-Framework GitHub repository 15 | Qlik-Deployment-Framework GitHub repository contains Qlik Script code that resides inside each QDF container, not the complete container. 16 | ## Qlik-Deployment-Framework GitHub content: 17 | - **Version1.7.5.txt** --> File containing version number and code modifications 18 | - **InitLink.qvs** --> Initiation script that links Qlik Sense/QlikView to 1.Init.qvs 19 | - **InitLinkSkip.qvs** --> InitLinkSkip.qvs removes script complexity and there by making debugging easier during developing 20 | - **3.Include/1.BaseVariable/1.Init.qvs** --> Main initiation script for both Qlik Sense and QlikView (run automatically by InitLink.qvs) 1.Init.qvs will validate and create global variables for the current environment. 21 | - **3.Include/1.BaseVariable/3.SystemVariables.qvs** --> Only for QlikView, loads system variables (filepath to logs and more) 22 | - **3.Include/2.Locale** --> contains locale files used during initiation 23 | - **3.Include/4.Sub** --> contains the most important function library, read more under README https://github.com/QlikDeploymentFramework/Qlik-Deployment-Framework/tree/master/3.Include/4.Sub 24 | 25 | -------------------------------------------------------------------------------- /3.Include/4.Sub/99.LoadAll.qvs: -------------------------------------------------------------------------------- 1 | // 2 | //### This script loads all sub functions in one single batch 3 | //### It's run automatically by 1.Init.qvs QDF during initiation 4 | //### $(Must_Include=$(vG.SubPath)\99.LoadAll.qvs); 5 | // 6 | $(Include=$(vG.$(vL.QDF.LinkShared_Folders)SubPath)\1.FileExist.qvs); 7 | $(Include=$(vG.$(vL.QDF.LinkShared_Folders)SubPath)\2.LoadVariableCSV.qvs); 8 | $(Include=$(vG.$(vL.QDF.LinkShared_Folders)SubPath)\3.LoadContainerMap.qvs); 9 | $(Include=$(vG.$(vL.QDF.LinkShared_Folders)SubPath)\4.GenericContainerLoader.qvs); 10 | $(Include=$(vG.$(vL.QDF.LinkShared_Folders)SubPath)\5.DoDir.qvs); 11 | $(Include=$(vG.$(vL.QDF.LinkShared_Folders)SubPath)\6.CreateFolder.qvs); 12 | $(Include=$(vG.$(vL.QDF.LinkShared_Folders)SubPath)\7.CalendarGen.qvs); 13 | $(Include=$(vG.$(vL.QDF.LinkShared_Folders)SubPath)\8.QVFileInfo.qvs); 14 | $(Include=$(vG.$(vL.QDF.LinkShared_Folders)SubPath)\9.QVDMigration.qvs); 15 | $(Include=$(vG.$(vL.QDF.LinkShared_Folders)SubPath)\11.DynamicContainerLoader.qvs); 16 | $(Include=$(vG.$(vL.QDF.LinkShared_Folders)SubPath)\12.Index.qvs); 17 | $(Include=$(vG.$(vL.QDF.LinkShared_Folders)SubPath)\13.NiceTrace.qvs); 18 | $(Include=$(vG.$(vL.QDF.LinkShared_Folders)SubPath)\14.QVDReduce.qvs); 19 | $(Include=$(vG.$(vL.QDF.LinkShared_Folders)SubPath)\15.ETLLog.qvs); 20 | 21 | 22 | // Loading in Qlikview Components, source avalible on GitHub 23 | // https://github.com/RobWunderlich/Qlikview-Components 24 | // Qlikview Components (Qvc) is a library of script subroutines and functions. 25 | // Disable Qvc in the script (before QDF initiation) setting the vG.QVCDisable=true flag 26 | 27 | 28 | // Section below is when integrating QVC and is disabled default. Enable QVC in Deploy Tool to activate this section 29 | //if trim(lower('$(vG.QVCDisable)'))='true' then // This is used to disable/enable QlikView Components library (Qvc) 30 | // 31 | // set vG.QVCDisable='$(vG.$(vL.QDF.LinkShared_Folders)SubPath)'; // vG.QVCDisable = true removes Qvc.qvs filename 32 | //else 33 | // set vG.QVCDisable='$(vG.$(vL.QDF.LinkShared_Folders)SubPath)Qvc.qvs'; // Not disabled will state the Qvc.qvs filename 34 | //endif 35 | // 36 | //$(Include=$(vG.QVCDisable)); 37 | 38 | // ************************************* 39 | // Functions written by Magnus Berg Qlik 40 | // ************************************* -------------------------------------------------------------------------------- /3.Include/4.Sub/6.CreateFolder.qvs: -------------------------------------------------------------------------------- 1 | 2 | // Create Folder function will create folder (if non existing) or folder structure. 3 | // First include the script: $(Include=$(vG.SubPath)\6.CreateFolder.qvs); 4 | // After execute (call) the Sub CreateFolder inside the script. 5 | // sub CreateFolder (vL.FolderName) vL.FolderName Is the folder name or folder structure to create 6 | // Example: call CreateFolder ('$(vG.QVDPath)\NorthWind'); // Will create NorthWind folder under vG.QVDPath 7 | 8 | 9 | SUB CreateFolder (vL.QDF.FolderName_1); 10 | $(Include=$(vG.SubPath)\1.FileExist.qvs); 11 | 12 | // Remove backslash in end 13 | do while right( '$(vL.QDF.FolderName_1)' , 1 ) ='\' 14 | let vL.QDF.FolderName_1 =left('$(vL.QDF.FolderName_1)',len('$(vL.QDF.FolderName_1)')-1); 15 | exit do unless right( '$(vL.QDF.FolderName_1)' , 1 ) ='\'; 16 | loop ; 17 | 18 | call vL.FileExist ('$(vL.QDF.FolderName_1)'); // Only execute on non-existing folder 19 | 20 | if vL.FileExist = 'false' then // If Folder do not exist it will be created. 21 | 22 | if left(trim('$(vG.BasePath)'),6)='lib://' then //validate if Qlik Senes is executing 23 | vL.QDF.CreateFolder: 24 | REPLACE LOAD * INLINE [//This file is created under QDF CreateFolder() function created folders]; 25 | store * from [vL.QDF.CreateFolder] into '$(vL.QDF.FolderName_1)\Info.txt' (txt,delimiter is ';' ); 26 | drop table [vL.QDF.CreateFolder]; 27 | else //QlikView is executing 28 | // Handle special characters in folder name for CMD pipeline 29 | // Ref: https://ss64.com/nt/syntax-redirection.html 30 | [vL.QDF.CreateFolder.EscapeCharsMap]: 31 | Mapping LOAD * Inline [ 32 | Char,EscapedChar 33 | &,^& 34 | \,^\ 35 | >,^> 36 | <,^< 37 | ^,^^ 38 | |,^| 39 | ]; 40 | Let vL.QDF.FolderIndex_tmp=index('$(vL.QDF.FolderName_1)','\',-1); 41 | let vL.QDF.FolderName_2=MapSubString('vL.QDF.CreateFolder.EscapeCharsMap',left('$(vL.QDF.FolderName_1)',vL.QDF.FolderIndex_tmp-1)); // Identifying folder path 42 | let vL.QDF.FolderName_3=MapSubString('vL.QDF.CreateFolder.EscapeCharsMap',mid('$(vL.QDF.FolderName_1)',vL.QDF.FolderIndex_tmp+1,Len('$(vL.QDF.FolderName_1)')));// Identifying folder name 43 | execute cmd.exe /Q /C pushd ^"$(vL.QDF.FolderName_2)^" & mkdir ^"$(vL.QDF.FolderName_3)^" & popd; // Mounting folder path and create Folder 44 | endif 45 | endif 46 | 47 | SET vL.QDF.FolderName_1= ; 48 | SET vL.QDF.FolderName_2= ; 49 | SET vL.QDF.FolderName_3= ; 50 | SET vL.QDF.FolderIndex_tmp= ; 51 | end sub 52 | 53 | // ************************************* 54 | // Functions written by Magnus Berg Qlik 55 | // ************************************* 56 | -------------------------------------------------------------------------------- /InitLinkSkip.qvs: -------------------------------------------------------------------------------- 1 | ; 2 | /* ___________________________________________________________________________ 3 | | Qlik Deployment Framework InitLinkSkip.qvs 4 | | InitLinkSkip.qvs is used to shorten script complexity when developing, 5 | | will only work after previously successful initiation 6 | | InitLinkSkip is used to bypass 1.Init.qvs for QlikView and Qlik Sense 7 | |___________________________________________________________________________*/ 8 | 9 | trace '### QDF Info, InitLinkSkip check if vG.BasePath exists'; //Writing information in log 10 | 11 | // Check if vG.BasePath variable exists, else exit the script 12 | If '$(vG.BasePath)'= '' then 13 | trace '### DF Warning, could not identify any valid container path, will exit'; 14 | trace '### DF Warning, use InitLink.qvs to generate global variables'; 15 | exit script; 16 | endif 17 | 18 | // Sub function vL.GetContainerStructure containing possible container folders (vL.ContainerStructure table) 19 | sub GetContainerStructure; 20 | vL.ContainerStructure: 21 | REPLACE LOAD * INLINE [ 22 | PhysicalFolderName, VariablePrefix, Subfolder, Comments 23 | Application, Application, , QlikView Applications are resided in subfolders under 1.Applications 24 | QVD, QVD, , QlikView Data files are stored in subfolders under 2.QVD 25 | Include, Include, , Folder where QlikView Include files are stored. These are script parts that are called from the main QlikView script. 26 | Mart, Mart, , "Resides QlikView Qvw marts (in subfolders) for data discovery usage, these folders could be shared." 27 | Config, Config, , Configuration and language files like Excel and txt. This folders could be shared to make configuration changes easier 28 | Script, Script, , Store for special scripts run by the publisher or scheduled tasks 29 | Export, Export, , "Folder used to store from QlikView exported data, probably txt or qvx" 30 | Import, Import, , Folder used to store import data from external systems 31 | BaseVariable, BaseVariable, Include, "Stores all the variables needed to use the framework, like paths inside the container" 32 | Locale, Locale, Include, "Locale for different regions, used for easy migration between regions" 33 | ConnString, ConnString, Include, Stores connection strings to data sources 34 | Sub, Sub, Include, "Store for sub routines, this is a way to reuse code between applications" 35 | ColorScheme, ColorScheme, Include, Company standard Color Scheme would be placed here 36 | Custom, Custom, Include, Store for custom include scripts 37 | Template, Template, , Used to identify Admin container and create extra variables used by Variable Editor 38 | Extract, Extract, QVD, Optional store for data extracts 39 | Transform, Transform, QVD, Optional store for data transformation 40 | Load, Load, QVD, Optional store for data load 41 | ]; 42 | end sub; 43 | 44 | // 99.LoadAll.qvs pre-loads QDF function-library within current container 45 | $(Include=$(vG.SubPath)\99.LoadAll.qvs); 46 | 47 | // Initiation of 4.Custom within home container 48 | $(Include=$(vG.BaseVariablePath)\4.Custom.qvs); // Loading 4.Custom from current container -------------------------------------------------------------------------------- /3.Include/4.Sub/README.md: -------------------------------------------------------------------------------- 1 | # 4.Sub function library 2 | 3 | 4.Sub folder contains the important function library used by 1.Init.qvs during initiation. This library is loaded in during initiation (executing 99.LoadAll.qvs) and adds additional functionallity when creating load scripts in Qlik Sense/QlikView. Sub function documantation is avalible on community in the QDF development guide https://community.qlik.com/docs/DOC-5306. 4 | 5 | - 99.LoadAll.qvs --> Auto loads all sub functions during initiation (by 1.Init.qvs) 6 | - 1.FileExist.qvs --> Validates file(s) or folder(s) , can be used to avoid errors during script load due to missing content. 7 | *call vL.FileExist('$(vG.QVDPath)\filename'); Variable vL.FileExist returns true or false.* 8 | - 2.LoadVariableCSV.qvs --> Load variables stored in csv files into the Qlik Script. This file is used by 1.Init to load Custom Global Variables. 9 | *call LoadVariableCSV('[My Variable File.csv]', [‘Search Tag’], [‘Container Prefix’], [‘Comments as variables’] [‘Container Map Mode’]);* 10 | - 3.LoadContainerMap.qvs --> Load and validate Container Map csv file, this function is used internaly by other functions 11 | sub LoadContainerMap(‘Container Map file’, ’Container name’, [' Optional $(vG.BasePath)']); 12 | - 4.GenericContainerLoader.qvs --> Creates Global Variable links (mounts) to other containers based on the Container Map. 13 | Call LCGV (‘Container Prefix’, [' Specific folder [;Additional folders separated by ;]); 14 | - 5.DoDir.qvs --> Will index selected folder/file structure and return a table containing file name and path under selected file system. 15 | Call DoDir (Scan Path, [Table Name], [Folders Only], [Single Folder], [Qualified Felds], [Hide QDF Templates]) 16 | - 6.CreateFolder.qvs --> create non existing folder or a folder structure. CreateFolder does not work in Qlik Sense without changing Engine to legacy mode. 17 | sub CreateFolder (vL.FolderName) 18 | - 7.CalendarGen.qvs --> Generic calendar generation script that enables scalable handling of creating and navigating multiple date fields 19 | *CALL CalendarGen('Date Field',[ 'Calendar Table'] [,‘Months Left Fiscal Date’] [,‘Min Date’, ‘Max Date’][,’Link Table’][,’DateFormat’]); * 20 | - 8.QVFileInfo.qvs --> Returns metadata (in table format) from Qlik files, at the moment QVW and QVD file formats. 21 | *Call QVFileInfo( 'Fully Qualified file Name',['Table Name']);* 22 | - 9.QVDMigration.qvs --> Migrates and consolidates qvd data between containers, using fixed file names or wildcard (*) migrating a qvd folder in one single statement. 23 | *Call QVDMigration (QVD Source File, QVD Destination File, [Select specific fields (, separator) leave blank for all fields], [Scrambled fields (, separator)], [Table Name Suffix], [Include Subfolders], [Format-Spec], [No of Records]);* 24 | - 10.QVDLoad.qvs --> Load up qvd files into a data model based on the meta-data headers in the qvd files. 25 | *Call QVDLoad(QVD Repository, [Select specific fields (, separator) leave blank for all fields], [Scrambled fields (, separator)], [Table Name Suffix], [Include Subfolders], [No of Records]);* 26 | - 11.DynamicContainerLoader.qvs --> Loads Global Variables within containers based on folder name. 27 | *Call DynamicContainerGlobalVariables (‘Container Path Name’, ['Single Folder [; Additional folders separated by ;]'] , [’Override Prefix’] , [’Use Shared Folder Container Map’]);* 28 | - 12.Index.qvs --> Index is functions that creates and maintains a set of indexes for Qlik Data files (QVD). These indexes are used when searching for data types across multiple qvd files this means that developers and power users select needed data using a simple command. 29 | - IndexAdd Will create the QVD indexes, should be done during qvd creation. 30 | *Call IndexAdd([‘QVD path and name’],['Index folder name'] ,['Container name'] ,['Tags'] ,['Alternative Index path']);* 31 | - IndexLoad Loads Qlik data based on combination of index criteria’s like file name, tags, table, fiels… 32 | *Call IndexLoad([‘QVD file name’],['Table Name'] ,['Index Folder Name'] ,['Tags'] ,['Fields'] ,['Index Only'] ,['Load Max Rows'] ,[ ['Alternative Index path'],[‘Load Expressions’]);* 33 | - IndexDel Delete index and optionally referring qvd file. 34 | *Call IndexDel(‘Index file name’,['Delete associated QVD files'] ,['Index Folder Name'] ,['Alternative Index path']);* 35 | -------------------------------------------------------------------------------- /3.Include/4.Sub/15.ETLLog.qvs: -------------------------------------------------------------------------------- 1 | // ___________________________________________________________________________ 2 | // Deployment Framework custom inclusion 3 | // 4 | // This script will build the ETL Log record for a common ETL Log schema to 5 | // be stored in a QVD. 6 | // 7 | // To do: 8 | // Sort out params to check for nulls and empty strings? 9 | // it would be good to allow an empty default. 10 | // ___________________________________________________________________________ 11 | 12 | /**************************************************************************************************** 13 | ETLLogEntry 14 | ----------- 15 | 16 | This function creates an ETL Log Entry in a resident table That can later be stored as desired 17 | using WriteETLLog. 18 | Params: vL.TableName = The name of the table that has been loaded for which an entry is to be created 19 | vL.TimeStamp = Default = now. The desired timestamp to be recorded. 20 | vL.StoreType = Default('QVD') - The format of the stored file if written. 21 | vL.Written = Default(True()) - Indicates if the loaded file was written 22 | vL.LogName = Default = ETLLog -The name of the output log table 23 | ****************************************************************************************************/ 24 | 25 | SUB ETLLogEntry(vL.TableName, vL.TimeStamp, vL.StoreType, vL.Written, vL.LogName); 26 | 27 | Trace 'Recording an ETL log entry for $(vL.TableName), vL.Written = $(vL.Written)'; 28 | 29 | // Initialise local vars 30 | Set vL.RecordCount = 0; 31 | 32 | // The name of the output log table, default ETLLog 33 | if isnull(vL.LogName) then 34 | Let vL.LogName = 'ETLLog'; 35 | end if; 36 | 37 | // What timestamp are we using to put in the log 38 | if isnull(vL.TimeStamp) then 39 | Let vL.TimeStamp = TimeStamp(Now()); 40 | end if; 41 | 42 | // What type of file are we writing 43 | if isnull(vL.StoreType) then 44 | let vL.StoreType = 'QVD'; 45 | end if; 46 | 47 | //Was the table intending to be stored 48 | if isnull(vL.Written) then 49 | let vL.Written = 'Unknown'; 50 | end if; 51 | 52 | // Get the record number count 53 | Let vL.RecordCount = NoOfRows('$(vL.TableName)'); 54 | 55 | 56 | // Create the ETLLog table entry 57 | 58 | Unqualify ETL_Timestamp, Target_Loaded, Target_Type, Records_Loaded, Stored; 59 | 60 | [$(vL.LogName)]: 61 | Load * Inline [ 62 | ETL_Timestamp, Target_Loaded, Target_Type, Stored, Records_Loaded 63 | $(vL.TimeStamp), $(vL.TableName), $(vL.StoreType), $(vL.Written), $(vL.RecordCount) 64 | ]; 65 | 66 | // Clean up 67 | SET vL.TableName=; 68 | SET vL.TimeStamp=; 69 | SET vL.RecordCount=; 70 | set vL.Written =; 71 | set vL.LogName =; 72 | 73 | END SUB 74 | 75 | 76 | 77 | /**************************************************************************************************** 78 | WriteETLLog 79 | ----------- 80 | 81 | This function writes an ETL Log file in CSV format. 82 | Params: vL.LogFile = Default(ETLLog) - the desired name of the logging file. 83 | vL.LogKeep = Default(True()) - determines whether the temporary ETL Log file is kept in the 84 | app. Set to False to avoid writing the file and keep in memory. 85 | vL.LogName = Default = ETLLog -The name of the current log table that should be exported 86 | ****************************************************************************************************/ 87 | 88 | SUB WriteETLLog(vL.LogFile, vL.LogKeep, vL.LogName) 89 | 90 | Trace 'Storing the ETL Log file, LogKeep parameter is set to: $(vL.LogKeep)'; 91 | 92 | // The name of the output log table, default ETLLog 93 | if isnull(vL.LogName) then 94 | Let vL.LogName = 'ETLLog'; 95 | end if; 96 | 97 | // Check to see if the ETLLog table exists, otherwise exit the sub 98 | if ISNULL(TableNumber('$(vL.LogName)')) then 99 | Set vL.LogFile =; 100 | Set vL.LogKeep =; 101 | set vL.LogName =; 102 | EXIT SUB; 103 | end if; 104 | 105 | // Initialise Variables 106 | if isnull(vL.LogFile) then 107 | Set vL.LogFile = 'ETLLog'; 108 | end if; 109 | 110 | if isnull(vL.LogKeep) then 111 | Set vL.LogKeep = True(); 112 | end if; 113 | 114 | // Check to see if the file already exists, if not add a header record. 115 | 116 | Unqualify Environment, App_Name, Stored, ETL_Timestamp, Target_Loaded, Target_Type, Records_Loaded; 117 | 118 | Call vL.FileExist('$(vG.ConfigPath)\$(vL.LogFile).csv'); 119 | If vL.FileExist = 'false' Then 120 | ETLLogWrite: 121 | Load * inline [ 122 | Environment, App_Name, Stored, ETL_Timestamp, Target_Loaded, Target_Type, Records_Loaded 123 | ]; 124 | else 125 | // if the file exists, load it so we can append the new records 126 | ETLLogWrite: 127 | Load 128 | Environment, App_Name, Stored, ETL_Timestamp, Target_Loaded, Target_Type, Records_Loaded 129 | FROM [$(vG.ConfigPath)\$(vL.LogFile).csv] (txt, utf8, embedded labels, delimiter is ',', msq); 130 | end if; 131 | 132 | // Append the generated log entries 133 | ETLLogWrite: 134 | Concatenate 135 | Load 136 | '$(vL.QDF)' as Environment, 137 | DocumentTitle() as App_Name, 138 | Stored, ETL_Timestamp, Target_Loaded, Target_Type, Records_Loaded 139 | Resident [$(vL.LogName)]; 140 | 141 | if $(vL.LogKeep) = True() then 142 | // Store the log file and drop the source table 143 | store ETLLogWrite into '$(vG.ConfigPath)\$(vL.LogFile).csv' (txt); 144 | drop table [$(vL.LogName)]; 145 | else 146 | // Do Nothing 147 | end if; 148 | 149 | // Cleanup 150 | drop table ETLLogWrite; 151 | Set vL.LogFile =; 152 | Set vL.LogKeep =; 153 | set vL.LogName =; 154 | 155 | END SUB 156 | 157 | // ************************************* 158 | // Functions written by Rod Stewart 159 | // ************************************* -------------------------------------------------------------------------------- /InitLink.qvs: -------------------------------------------------------------------------------- 1 | ; 2 | /* ___________________________________________________________________________ 3 | | Qlik Deployment Framework InitLink.qvs 4 | | InitLink.qvs is the container identifier 5 | | InitLink is used as "sling shot" to 1.Init.qvs for QlikView and Qlik Sense 6 | |___________________________________________________________________________*/ 7 | 8 | trace '### QDF Info, InitLink trying to link to initiation script'; //Writing information in log 9 | 10 | // Run Container initiation 11 | 12 | // Modify setting if the default .Include folder is changed, usually leve as is 13 | LET vL.QDF.IncludeFolder='Include'; 14 | 15 | // Modify setting if the default .BaseVariable folder is changed, usually leve as is 16 | SET vL.QDF.BaseVariableFolder='BaseVariable'; 17 | 18 | LET vL.QDF.RootPath_tmp='$(vG.RootPath)'; // vL.QDF.RootPath_tmp is used to identify global variable cache 19 | LET vL.QDF.BasePath_tmp='$(vG.BasePath)'; // vL.QDF.BasePath_tmp is used to identify global variable cache 20 | 21 | // Cleanup, Removing old values 22 | SET vG.BasePath=; 23 | SET vL.QDF.BaseVariablePath=; 24 | SET vG.RootPath=; 25 | 26 | //***************** Initiation for Qlik Sense and QlikView ********************************** 27 | // Qlik Sense additions Validating if LIB root exists if yes then add this as vG.RootPath 28 | // Validate Separate LIB mounts 29 | if not '$(vG.HomeContainer)' = '' and not IsNull(filesize('lib://$(vG.HomeContainer)/Initlink.qvs')) = -1 then 30 | LET vG.BasePath= 'lib://$(vG.HomeContainer)/'; 31 | trace '### DF Info, identified Sense home container $(vG.BasePath) (Separate LIB mounts)'; 32 | elseif not '$(vG.HomeContainer)' = '' and not IsNull(filesize('$(vG.HomeContainer)/Initlink.qvs')) = -1 then 33 | LET vG.BasePath= '$(vG.HomeContainer)/'; 34 | trace '### DF Info, identified Sense home container $(vG.BasePath) (Separate LIB mounts)'; 35 | elseif '$(vG.HomeContainer)' = '' and not IsNull(filesize('lib://Shared/*')) = -1 then 36 | LET vG.BasePath= 'lib://Shared/'; 37 | trace '### DF Info, identified Sense Shared home container (Separate LIB mounts)'; 38 | elseif '$(vG.HomeContainer)' = '' and not IsNull(filesize('lib://shared/*')) = -1 then 39 | LET vG.BasePath= 'lib://shared/'; 40 | trace '### DF Info, identified Sense shared home container (Separate LIB mounts)'; 41 | else // Validate single LIB mount 42 | if not '$(vG.RootContainer)' = '' and not IsNull(filesize('lib://$(vG.RootContainer)/*')) = -1 then 43 | LET vG.RootPath= 'lib://$(vG.RootContainer)/'; 44 | trace '### DF Info, identified Sense root path $(vG.RootPath) (single LIB mount)'; 45 | SET vG.RootContainer = ; 46 | elseif not '$(vG.RootContainer)' = '' then 47 | trace '### DF Warning, could not find root container with name $(vG.RootContainer)'; 48 | SET vG.RootContainer = ; 49 | elseif not IsNull(filesize('lib://Root/*')) = -1 then 50 | LET vG.RootPath= 'lib://Root/'; 51 | trace '### DF Info, identified Sense root path $(vG.RootPath) (single LIB mount)'; 52 | elseif not IsNull(filesize('lib://root/*')) = -1 then 53 | LET vG.RootPath= 'lib://root/'; 54 | trace '### DF Info, identified Sense root path $(vG.RootPath) (single LIB mount)'; 55 | endif 56 | 57 | // Validate fixed root url 58 | if not '$(vG.HomeContainer)'='' and not IsNull(filesize('$(vG.RootPath)$(vG.HomeContainer)\Initlink.qvs')) = -1 then 59 | LET vG.BasePath= '$(vG.RootPath)$(vG.HomeContainer)\'; 60 | trace '### DF Info, identified Sense home container $(vG.BasePath)'; 61 | elseif not '$(vG.RootPath)' = '' and not IsNull(filesize('$(vG.RootPath)99.Shared_Folders/*')) = -1 then 62 | LET vG.BasePath= '$(vG.RootPath)99.Shared_Folders/'; 63 | trace '### DF Info, identified Sense home container $(vG.BasePath)'; 64 | elseif not '$(vG.RootPath)' = '' then // Search for Initlink.qvs in a valid container under Root 65 | for each vL.QDF.DoDir in dirlist ('$(vG.RootPath)*') 66 | if filesize('$(vL.QDF.DoDir)\Initlink.qvs') > 1 then 67 | LET vG.BasePath= '$(vL.QDF.DoDir)\'; 68 | trace '### DF Info, identified Sense home container $(vG.BasePath)'; 69 | endif 70 | exit for when not '$(vG.BasePath)'=''; 71 | next vL.QDF.DoDir 72 | set vL.QDF.DoDir=; 73 | 74 | else // This is the QlikView vG.BasePath initiation section 75 | LET vG.BasePath=; 76 | for vL.x_loop =1 to 20-1 77 | LET vL.QDF.InitLinkPath_tmp='$(vL.QDF.InitLinkPath)'; 78 | if FileTime('$(vL.QDF.InitLinkPath)InitLink.qvs') > 0 then 79 | // Set vG.BasePath based on InitLink.qvs location 80 | LET vG.BasePath=left(DocumentPath(),index(DocumentPath(),'\', -(substringcount( '$(vL.QDF.InitLinkPath)','\' )+1))); 81 | endif 82 | LET vL.QDF.InitLinkPath='..\'&'$(vL.QDF.InitLinkPath_tmp)'; 83 | exit for when not '$(vG.BasePath)'= '' 84 | next 85 | SET vL.QDF.InitLinkPath = ; 86 | SET vL.QDF.InitLinkPath_tmp = ; 87 | SET vL.x_loop = ; 88 | endif 89 | endif 90 | 91 | if '$(vG.BasePath)'= '' then // validate initiation 92 | trace '### QDF Warning, could not identify any valid container path, will exit'; 93 | trace '### QDF Warning, if using Qlik Sense add SET vG.HomeContainer=container name before InitLink.qvs'; 94 | LET vG.BasePath=; 95 | exit script; 96 | endif 97 | 98 | SET vG.HomeContainer = ; 99 | SET vG.RootContainer = ; 100 | //***************** Initiation for Qlik Sense and QlikView done ********************************** 101 | 102 | //Identify BaseVariablePath location during initiation 103 | for each vL.QDF.DoDir in dirlist ('$(vG.BasePath)*') //Search for a valid container under Root 104 | if right('$(vL.QDF.DoDir)',len('$(vL.QDF.IncludeFolder)'))='$(vL.QDF.IncludeFolder)' then 105 | for each vL.QDF.DoDir2 in dirlist ('$(vL.QDF.DoDir)\*') //Search for a valid container under Root 106 | if right('$(vL.QDF.DoDir2)',len('$(vL.QDF.BaseVariableFolder)'))='$(vL.QDF.BaseVariableFolder)' then 107 | LET vL.QDF.BaseVariablePath= '$(vL.QDF.DoDir2)\'; 108 | endif 109 | exit for when right('$(vL.QDF.DoDir2)',len('$(vL.QDF.BaseVariableFolder)'))='$(vL.QDF.BaseVariableFolder)'; 110 | next vL.QDF.DoDir2 111 | endif 112 | exit for when right('$(vL.QDF.DoDir)',len('$(vL.QDF.IncludeFolder)'))='$(vL.QDF.IncludeFolder)'; 113 | next vL.QDF.DoDir 114 | SET vL.QDF.DoDir=; 115 | SET vL.QDF.DoDir2=; 116 | 117 | $(Include=$(vL.QDF.BaseVariablePath)1.Init.qvs); -------------------------------------------------------------------------------- /3.Include/4.Sub/5.DoDir.qvs: -------------------------------------------------------------------------------- 1 | // ___________________________________________________________________________ 2 | // Deployment Framework DoDir sub function 5.DoDir.qvs 3 | // 4 | // Returns a Table containing files and path in selected file system (vL.QDF.DoDirRoot) 5 | // First include the DoDir Function $(Include=$(vG.SubPath)\5.DoDir.qvs); 6 | // Use the function DoDir to execute. examples: 7 | // call DoDir ('$(vG.RootPath)'); //Simple Example 8 | // call DoDir ('$(vG.RootPath)\*.qvd'); //Simple Example 9 | // call DoDir ('$(vG.BasePath),Table Name)'); //Change Table name 10 | // 11 | sub DoDir (vL.QDF.DoDirRoot,vL.QDF.DoDirTableName,vL.QDF.FoldersOnly,vL.QDF.SingleFolder,vL.QDF.QualifyFelds,vL.QDF.Template_Exeptions) 12 | 13 | let vL.QDF.DoDirRoot=trim('$(vL.QDF.DoDirRoot)'); // Trim vL.QDF.DoDirRoot 14 | let vL.QDF.Filename=; // remove variable (if exists) 15 | 16 | if '$(vL.QDF.DoDirTableName)'='' then // If no TableName specified use DoDirFileList 17 | SET vL.QDF.DoDirTableName = 'DoDirFileList'; 18 | endif; 19 | 20 | if lower('$(vL.QDF.QualifyFelds)')='true' then // if qualify switch set to true 21 | LET vL.QDF.QualifyFelds='$(vL.QDF.DoDirTableName).'; // Set vL.QDF.QualifyFelds as the same as table name 22 | else 23 | LET vL.QDF.QualifyFelds=; 24 | endif 25 | unqualify $(vL.QDF.QualifyFelds)FullyQualifiedName,$(vL.QDF.QualifyFelds)DoDirFileSize,$(vL.QDF.QualifyFelds)DoDirFileTime,$(vL.QDF.QualifyFelds)DoDirFileName,$(vL.QDF.QualifyFelds)DoDirContainerPath,$(vL.QDF.QualifyFelds)DoDirFileExtension,$(vL.QDF.QualifyFelds)DoDirFileNameCount ; 26 | sub vL.QDF.DoDirTableName(vL.QDF.DoDirFile); //DoDir table generate sub 27 | [$(vL.QDF.DoDirTableName)]: 28 | ADD 29 | Load '$(vL.QDF.DoDirFile)' as '$(vL.QDF.QualifyFelds)FullyQualifiedName', 30 | FileSize( '$(vL.QDF.DoDirFile)' ) as '$(vL.QDF.QualifyFelds)DoDirFileSize', 31 | timestamp(FileTime( '$(vL.QDF.DoDirFile)' ),'$(TimestampFormat)') as '$(vL.QDF.QualifyFelds)DoDirFileTime', 32 | subfield(replace('$(vL.QDF.DoDirFile)','/','\'),'\',-1) as '$(vL.QDF.QualifyFelds)DoDirFileName', 33 | replace(subfield(replace('$(vL.QDF.DoDirFile)','/','\'),'$(vL.QDF.DoDirRoot)',-1),'\\','\') as '$(vL.QDF.QualifyFelds)DoDirContainerPath', 34 | if( lower('$(vL.QDF.FoldersOnly)')='true', '' , upper(subfield('$(vL.QDF.DoDirFile)','.',-1))) as '$(vL.QDF.QualifyFelds)DoDirFileExtension' 35 | autogenerate 1; 36 | end sub 37 | 38 | // Check if a specific File Extension is used, separate out extension and filename Also special for Qlik Sense lib folders 39 | if index('$(vL.QDF.DoDirRoot)','*')>0 and FindOneOf('$(vL.QDF.DoDirRoot)','\')>0 then 40 | LET vL.QDF.Specific_File_Type= right('$(vL.QDF.DoDirRoot)',len( '$(vL.QDF.DoDirRoot)')-(index( '$(vL.QDF.DoDirRoot)', '.',-1))+1); // Get file extension 41 | if FindOneOf('$(vL.QDF.Specific_File_Type)','\')>0 then // If filetype contains \ it's probably a folder 42 | LET vL.QDF.Specific_File_Type=''; // remove filetype 43 | endif 44 | let vL.QDF.Filename=left(right('$(vL.QDF.DoDirRoot)',len('$(vL.QDF.DoDirRoot)')-index('$(vL.QDF.DoDirRoot)','\',-1)),len(right('$(vL.QDF.DoDirRoot)',len('$(vL.QDF.DoDirRoot)')-index('$(vL.QDF.DoDirRoot)','\',-1)))-len('$(vL.QDF.Specific_File_Type)')); 45 | LET vL.QDF.DoDirRoot= left ('$(vL.QDF.DoDirRoot)',index('$(vL.QDF.DoDirRoot)','\',-1)); // Remove filename from path 46 | else 47 | LET vL.QDF.Specific_File_Type= '*'; 48 | endif 49 | 50 | LET vL.QDF.DoDirRootTmp= '$(vL.QDF.DoDirRoot)'; 51 | 52 | if index(trim('$(vL.QDF.DoDirRootTmp)'),'\\',-1)>2 then // Remove double \\ in path, except in the beginning used in UNC path 53 | LET vL.QDF.DoDirRootTmp=left( '$(vL.QDF.DoDirRootTmp)' , (index( '$(vL.QDF.DoDirRootTmp)', '\\', -1 )-1))&right('$(vL.QDF.DoDirRootTmp)', (len( '$(vL.QDF.DoDirRootTmp)' ) -index( '$(vL.QDF.DoDirRootTmp)', '\\', -1 ))); 54 | endif 55 | 56 | if lower('$(vL.QDF.FoldersOnly)')='true' then // If folders only is used (vL.QDF.FoldersOnly) execute vL.QDF.DoDirTableName to add first folder 57 | call vL.QDF.DoDirTableName('$(vL.QDF.DoDirRootTmp)'); 58 | endif 59 | 60 | sub vL.DoDirTmp (vL.QDF.DoDirRootTmp) // DoDir main Sub 61 | if not lower('$(vL.QDF.FoldersOnly)')='true' then // If folders only is used (vL.QDF.Specific_File_Type) do not execute vL.QDF.DoDirTableName 62 | for each vL.QDF.DoDirFile in filelist ('$(vL.QDF.DoDirRootTmp)$(vL.QDF.Filename)*$(vL.QDF.Specific_File_Type)') // Index Files 63 | call vL.QDF.DoDirTableName('$(vL.QDF.DoDirFile)'); 64 | next vL.QDF.DoDirFile 65 | endif 66 | 67 | if not lower('$(vL.QDF.SingleFolder)')='true' then 68 | for each vL.QDF.DirTmp in dirlist ('$(vL.QDF.DoDirRootTmp)*' ) // Index folders 69 | if not lower('$(vL.QDF.Template_Exeptions)')='true' then // Validate if switch to remove QDF templates/demo is activated (vL.QDF.Template_Exeptions) 70 | if lower('$(vL.QDF.FoldersOnly)')='true' then // If folders only is used (vL.QDF.FoldersOnly) execute vL.QDF.DoDirTableName 71 | call vL.QDF.DoDirTableName('$(vL.QDF.DirTmp)'); 72 | endif 73 | call vL.DoDirTmp ('$(vL.QDF.DirTmp)\') 74 | 75 | // If vL.QDF.Template_Exeptions is true validate and ignore 0. or # on folders (used for Templates and examples) 76 | elseif num(subfield(right('$(vL.QDF.DirTmp)',(len('$(vL.QDF.DirTmp)')-len('$(vL.QDF.DoDirRootTmp)'))), '.' , 1 )) >0 and substringcount (right('$(vL.QDF.DirTmp)',(len('$(vL.QDF.DirTmp)')-(len('$(vL.QDF.DoDirRootTmp)')+1))),'#') = 0 then 77 | if lower('$(vL.QDF.FoldersOnly)')='true' then // If folders only is used (vL.QDF.FoldersOnly) execute vL.QDF.DoDirTableName 78 | call vL.QDF.DoDirTableName('$(vL.QDF.DirTmp)'); 79 | endif 80 | call vL.DoDirTmp ('$(vL.QDF.DirTmp)\') 81 | endif 82 | 83 | next vL.QDF.DirTmp 84 | endif 85 | end sub 86 | 87 | 88 | call vL.DoDirTmp ('$(vL.QDF.DoDirRootTmp)') 89 | 90 | if NoOfFields('$(vL.QDF.DoDirTableName)') > 0 then // Validate DoDir table 91 | 92 | // Join file count information field 93 | Left join ([$(vL.QDF.DoDirTableName)]) 94 | Add 95 | Load [$(vL.QDF.QualifyFelds)DoDirFileName], 96 | count([$(vL.QDF.QualifyFelds)DoDirFileName]) as [$(vL.QDF.QualifyFelds)DoDirFileNameCount] 97 | Resident [$(vL.QDF.DoDirTableName)] 98 | group by [$(vL.QDF.QualifyFelds)DoDirFileName]; 99 | 100 | else 101 | trace '### QDF Info, DoDir cant find file/path $(vL.QDF.DoDirRoot)'; 102 | endif 103 | 104 | SET vL.QDF.DoDirTableName =; 105 | SET vL.QDF.DoDirFile=; 106 | SET vL.QDF.DoDirRootTmp=; 107 | SET vL.QDF.DirTmp=; 108 | SET vL.QDF.Template_Exeptions=; 109 | SET vL.QDF.Specific_File_Type=; 110 | SET vL.QDF.SingleFolder=; 111 | SET vL.QDF.FoldersOnly=; 112 | SET vL.QDF.QualifyFelds=; 113 | SET vL.QDF.Filename=; 114 | end sub 115 | 116 | // ************************************* 117 | // Functions written by Magnus Berg Qlik 118 | // ************************************* 119 | -------------------------------------------------------------------------------- /3.Include/4.Sub/4.GenericContainerLoader.qvs: -------------------------------------------------------------------------------- 1 | // ____________________________________________________________ 2 | // Deployment Framework BaseVariable 4.GenericContainerLoader// 3 | // All path are based on vG.BasePath // 4 | // This script is used to connect to any container // 5 | // This script should only be accessed via the LCGV function 6 | // SUB LCGV(‘Container Path Name’,['Optional Single Folder']); 7 | // Example: call LCGV('1.AcmeStore'); 8 | //___________________________________________________________// 9 | 10 | SUB LoadContainerGlobalVariables(vL.QDF.ContainerName,vL.QDF.SingleFolder,vL.QDF.Alias); 11 | 12 | sub vL.QDF.FindFolders; 13 | if not '$(vL.QDF.Subfolder)'='' then 14 | for each vL.QDF.DoDir in dirlist ('$(vG.$(vL.QDF.Alias)BasePath)$(vL.PhysicalFolderName)*') 15 | if right('$(vL.QDF.DoDir)',len('$(vL.QDF.Subfolder)'))='$(vL.QDF.Subfolder)' then 16 | LET vL.QDF.BasePath='$(vL.QDF.DoDir)\'; 17 | endif 18 | next vL.QDF.DoDir 19 | else 20 | LET vL.QDF.BasePath='$(vG.$(vL.QDF.Alias)BasePath)$(vL.PhysicalFolderName)'; 21 | endif 22 | for each vL.QDF.DoDir in dirlist ('$(vL.QDF.BasePath)*') //Search for a valid container under Root 23 | if right('$(vL.QDF.DoDir)',len('$(vL.QDF.PhysicalFolderName)'))='$(vL.QDF.PhysicalFolderName)' then 24 | SET vG.$(vL.QDF.Alias)$(vL.QDF.VariablePrefix)Path='$(vL.QDF.DoDir)\'; // Set Global Variable using the vL.QDF.Alias default set to vL.ContainerPathName 25 | endif 26 | exit for when right('$(vL.QDF.DoDir)',len('$(vL.QDF.PhysicalFolderName)'))='$(vL.QDF.PhysicalFolderName)' 27 | next vL.QDF.DoDir 28 | SET vL.QDF.DoDir=; 29 | endsub 30 | 31 | 32 | // Writing information in log 33 | trace '### QDF Info, 2.GenericContainerLoader.qvs Started'; 34 | 35 | LET vL.QDF.ContainerName=trim('$(vL.QDF.ContainerName)'); // Trim vL.QDF.ContainerName from white spaces 36 | 37 | if '$(vL.QDF.Alias)'='' then // If manual added alias exists use VariablePrefix found in container map 38 | let vL.QDF.Alias= '$(vL.QDF.ContainerName)'; // this Alias replaces the prefix as global variable name 39 | else 40 | let vL.QDF.Alias= PurgeChar(trim('$(vL.QDF.Alias)'),'=;,- '&chr(39)); 41 | trace '### QDF Info, Alias: $(vL.QDF.Alias) found, will replace: $(vL.QDF.ContainerName) prefix name' ; 42 | endif 43 | 44 | // Qlik Sense folder repository validation 45 | if filesize('lib://$(vL.QDF.ContainerName)/Initlink.qvs') > 1 then 46 | trace '### QDF Info, Qlik Sense folder repository (Separate LIB mount)'; 47 | SET vG.$(vL.QDF.Alias)BasePath = 'lib://$(vL.QDF.ContainerName)/'; 48 | SET vL.ContainerPathName='$(vL.QDF.ContainerName)'; 49 | else 50 | 51 | $(Include=$(vG.SubPath)\3.LoadContainerMap.qvs); 52 | 53 | // Load container map and variables by using LoadContainerMap function 54 | // vL.ContainerFolderName, vL.ContainerPathName, vL.RootPath are all retrieved from LoadContainerMap sub function 55 | let vL.QDF.ContainerMapPath = '$(vG.BaseVariablePath)\ContainerMap.csv'; 56 | call LoadContainerMap('$(vL.QDF.ContainerMapPath)','$(vL.QDF.ContainerName)'); // Using LoadContainerMap with special switches the Container links will be populated automatically 57 | 58 | 59 | // If vL.ContainerPathName can't be found in the local ContainerMap try the shared ContainerMap 60 | if '$(vL.ContainerPathName)' = '' and FileSize('$(vG.SharedBaseVariablePath)\ContainerMap.csv') > 0 then 61 | let vL.QDF.ContainerMapPath = '$(vG.SharedBaseVariablePath)\ContainerMap.csv'; 62 | call LoadContainerMap('$(vL.QDF.ContainerMapPath)','$(vL.QDF.ContainerName)'); 63 | endif 64 | 65 | // Base Search Path $(vG.BasePath) for this container 66 | SET vG.$(vL.QDF.Alias)BasePath = '$(vL.RootPath)$(vL.ContainerFolderName)\'; 67 | endif 68 | 69 | if not '$(vL.ContainerPathName)' = '' then 70 | // Validates the connected folder path 71 | // call function to check if the folder exists 72 | $(Include=$(vG.SubPath)\1.FileExist.qvs); 73 | call vL.FileExist ('$(vG.$(vL.QDF.Alias)BasePath)*'); 74 | // If file exists continue 75 | if vL.FileExist = 'false' then 76 | trace '### QDF Warning, vG.$(vL.QDF.Alias)BasePath missing'; 77 | SET vG.$(vL.QDF.Alias)BasePath = ; 78 | else 79 | // Writing information in log 80 | trace '### QDF Info, found $(vL.ContainerPathName) container, mounting as vG.$(vL.QDF.Alias)BasePath' ; 81 | if not '$(vL.Comment)' = '' then 82 | trace '### DF Info $(vL.Comment)'; 83 | endif 84 | 85 | // Creating Sub Folder Path Global Variables to main folders 86 | Call GetContainerStructure ; 87 | FOR vL.QDF.VariableLoop = 0 to NoOfRows('vL.ContainerStructure')-1; 88 | 89 | let vL.QDF.PhysicalFolderName = Peek(FieldName(1,'vL.ContainerStructure'),$(vL.QDF.VariableLoop), vL.ContainerStructure); 90 | let vL.QDF.VariablePrefix = Peek(FieldName(2,'vL.ContainerStructure'),$(vL.QDF.VariableLoop), vL.ContainerStructure); 91 | let vL.QDF.Subfolder = Peek(FieldName(3,'vL.ContainerStructure'),$(vL.QDF.VariableLoop), vL.ContainerStructure); 92 | 93 | // If vL.QDF.SingleFolder mode not used add all path 94 | if '$(vL.QDF.SingleFolder)'='' then 95 | call vL.QDF.FindFolders ; 96 | else 97 | LET vL.QDF.SubStringSplitt=';'&'$(vL.QDF.SingleFolder)'&';'; // Creating a variable used for easy substring splitt 98 | for vL.QDF.SubString=1 to substringcount ('$(vL.QDF.SubStringSplitt)',';') -1 // loop as many times there are folders defined (separated by ;) 99 | if index(TextBetween('$(vL.QDF.SubStringSplitt)' , ';', ';' , vL.QDF.SubString ),'$(vL.QDF.VariablePrefix)') > 0 then // Pick folder in substring (vL.QDF.SubStringSplitt) based on vL.QDF.SubString 100 | call vL.QDF.FindFolders ; 101 | endif; 102 | next vL.QDF.SubString; 103 | endif 104 | 105 | Next vL.QDF.VariableLoop 106 | 107 | // Dropping ContainerStructure table when Base Global Variables are read into QlikView 108 | drop table vL.ContainerStructure ; 109 | 110 | // If vL.QDF.SingleFolder mode is used remove vG.$(vL.QDF.Alias)BasePath (if not BasePath exlicitly been selected) 111 | if not '$(vL.QDF.SingleFolder)'='' and not trim('$(vL.QDF.SingleFolder)') = 'BasePath' then 112 | SET vG.$(vL.QDF.Alias)BasePath = ; 113 | endif 114 | 115 | // Writing information in log 116 | trace '### QDF Info, $(vL.QDF.Alias) Finished'; 117 | 118 | else 119 | trace '### QDF Warning, Could not find $(vL.QDF.ContainerName) container in Container Map'; 120 | endif; 121 | else 122 | trace '### QDF Warning, Could not find $(vL.QDF.ContainerName) container in Container Map'; 123 | endif; 124 | 125 | 126 | // Clean up 127 | // Remove local variables 128 | 129 | SET vL.ContainerFolderName=; 130 | SET vL.QDF.PhysicalFolderName=; 131 | SET vL.QDF.VariablePrefix=; 132 | SET vL.QDF.VariableLoop=; 133 | SET vL.QDF.Subfolder=; 134 | set vL.QDF.VariableLoop=; 135 | SET vL.QDF.BasePath=; 136 | SET vL.QDF.ContainerMapPath = ; 137 | SET vL.ContainerPathName=; 138 | SET vL.RootPath=; 139 | SET vL.FileExist=; 140 | SET vL.QDF.ContainerName=; 141 | SET vL.Comment =; 142 | SET vL.QDF.SingleFolder=; 143 | SET vL.QDF.SubStringSplitt=; 144 | SET vL.QDF.SubString=; 145 | SET vL.QDF.Alias=; 146 | end sub 147 | 148 | SUB LCGV(vL.QDF.ContainerName_tmp,vL.QDF.SingleFolder_tmp,vL.QDF.Alias_tmp); // Alias for LoadContainerGlobalVariables 149 | call LoadContainerGlobalVariables('$(vL.QDF.ContainerName_tmp)','$(vL.QDF.SingleFolder_tmp)','$(vL.QDF.Alias_tmp)'); 150 | SET vL.QDF.ContainerName_tmp=; 151 | SET vL.QDF.SingleFolder_tmp=; 152 | SET vL.QDF.Alias_tmp=; 153 | end sub 154 | 155 | // ************************************* 156 | // Functions written by Magnus Berg Qlik 157 | // ************************************* -------------------------------------------------------------------------------- /3.Include/4.Sub/11.DynamicContainerLoader.qvs: -------------------------------------------------------------------------------- 1 | // __________________________________________________________________________ 2 | // Qlik Deployment Framework BaseVariable 11.DynamicContainerGlobalVariables.qvs 3 | // All path are based on vG.BasePath 4 | // This script is used to dynamic connect to container folders 5 | // This script should only be accessed from QlikView via the LoadContainerGlobalVariables function 6 | // SUB DynamicContainerGlobalVariables ('Container Path Name',['Optional Single Folder'], ['Optional use alternative Container Map']); 7 | // Example: call DynamicContainerGlobalVariables('1.AcmeStore'); 8 | // Example: call DCGV('1.AcmeStore'); 9 | //____________________________________________________________________________ 10 | 11 | SUB DynamicContainerGlobalVariables(vL.QDF.ContainerName,vL.QDF.SingleFolder,vL.QDF.OverridePrefix); 12 | 13 | // Writing information in log 14 | trace '### QDF DynamicContainerGlobalVariables Started'; 15 | SET vL.ContainerFolderName = ; // Reset variable 16 | SET vL.QDF.BasePath = ; // Reset variable 17 | set vL.HideQDFTemplates ='true'; //Default use qualified folders and hide QDF templates 18 | 19 | if filesize('$(vG.SharedBaseVariablePath)\ContainerMap.csv') >0 then // If null use default ContainerMap else Shared ContainerMap is used 20 | let vL.QDF.ContainerMapPath = '$(vG.SharedBaseVariablePath)\ContainerMap.csv'; 21 | else 22 | let vL.QDF.ContainerMapPath = '$(vG.BaseVariablePath)\ContainerMap.csv'; 23 | end if 24 | 25 | 26 | // Load container mapping table and variables by using LoadContainerMap function 27 | 28 | // If no container specified use home container 29 | if '$(vL.QDF.ContainerName)' = '' then 30 | SET vL.QDF.BasePath = '$(vG.BasePath)'; 31 | SET vL.ContainerPathName=; 32 | set vL.Comment='Loading vG.BasePath Global Path Variables'; 33 | SET vL.ContainerFolderName='BasePath'; 34 | 35 | // Use folder or lib path is specified instead of a ontainer 36 | elseif SubstringCount('$(vL.QDF.ContainerName)','\') > 0 or SubstringCount('$(vL.QDF.ContainerName)','/') > 0 then 37 | SET vL.QDF.BasePath = '$(vL.QDF.ContainerName)\'; 38 | SET vL.ContainerPathName=; 39 | set vL.Comment='Loading vG.BasePath Global Path Variables'; 40 | SET vL.ContainerFolderName='BasePath'; 41 | // If specifying a path and folders dissable special folder syntax 42 | if not '$(vL.QDF.SingleFolder)'='' then 43 | set vL.HideQDFTemplates =; //Revoke qualified folders if path is specified 44 | endif 45 | 46 | // Qlik Sense optional separate LIB mount folder validation 47 | elseif filesize('lib://$(vL.QDF.ContainerName)/Initlink.qvs') > 1 then 48 | trace '### QDF Info, Qlik Sense folder repository (Separate LIB mount)'; 49 | SET vL.QDF.BasePath = 'lib://$(vL.QDF.ContainerName)/'; 50 | SET vL.ContainerPathName='$(vL.QDF.ContainerName)'; 51 | 52 | //Search container map for containername 53 | else 54 | call LoadContainerMap('$(vL.QDF.ContainerMapPath)','$(vL.QDF.ContainerName)'); // Using LoadContainerMap with special switches the Container links will be populated automatically 55 | if trim('$(vL.ContainerPathName)')= '$(vL.QDF.ContainerName)' then // If container found by LoadContainerMap sub function 56 | SET vL.QDF.BasePath = '$(vL.RootPath)$(vL.ContainerFolderName)\'; 57 | 58 | elseif not IsNull(filesize('$(vL.QDF.ContainerName)')) = -1 then // If container not found it could be a folder path instead of a Map reference 59 | SET vL.QDF.BasePath = '$(vL.QDF.ContainerName)\'; 60 | // SET vL.ContainerFolderName = 'No folder found, Custom path used'; 61 | endif; 62 | endif; 63 | 64 | if not '$(vL.QDF.BasePath)'='' then // Execute only if container found 65 | 66 | if not '$(vL.QDF.OverridePrefix)'='' then // If OverridePrefix swish is used set the prefix 67 | LET vL.ContainerPathName='$(vL.QDF.OverridePrefix)'; 68 | trace '### QDF Info, Override Prefix switsh $(vL.QDF.OverridePrefix) used'; 69 | endif; 70 | 71 | Call DoDir ('$(vL.QDF.BasePath)','vL.DoDir_Tmp_Table','true','','true','$(vL.HideQDFTemplates)'); // Creates DoDir Table 'vL.DoDir_Tmp_Table' on folders only from vL.QDF.BasePath path 72 | 73 | if NoOfFields('vL.DoDir_Tmp_Table') > 0 then // Validate if DoDir table exists 74 | 75 | // loop through DoDir Table 76 | let vL.QDF.xxxxx = NoOfRows('vL.DoDir_Tmp_Table'); 77 | 78 | for vL.QDF.ttttt = 0 to vL.QDF.xxxxx-1 79 | 80 | LET vL.QDF.VariablePrefix = PurgeChar(subfield(peek('vL.DoDir_Tmp_Table.DoDirFileName',$(vL.QDF.ttttt),'vL.DoDir_Tmp_Table'),'.',-1),'=;,- '&chr(39)); 81 | LET vL.QDF.PhysicalFolderName = peek('vL.DoDir_Tmp_Table.FullyQualifiedName',$(vL.QDF.ttttt),'vL.DoDir_Tmp_Table'); 82 | LET vL.QDF.DuplicatedFolders=peek('vL.DoDir_Tmp_Table.DoDirFileNameCount',$(vL.QDF.ttttt),'vL.DoDir_Tmp_Table'); 83 | LET vL.QDF.SubStringSplitt=';'&'$(vL.QDF.SingleFolder)'&';'; // Creating a variable used for easy substring splitt 84 | For vL.QDF.SubString=1 to substringcount ('$(vL.QDF.SubStringSplitt)',';') -1 // loop as many times there are folders defined (separated by ;) 85 | if TextBetween('$(vL.QDF.SubStringSplitt)' , ';', ';' , vL.QDF.SubString ) = '$(vL.QDF.VariablePrefix)' or '$(vL.QDF.SingleFolder)'='' then 86 | if vL.QDF.DuplicatedFolders > 1 then //If duplicated folders found send error message 87 | trace '### QDF Warning, Found duplicated folders of $(vL.QDF.VariablePrefix) in location $(vL.QDF.PhysicalFolderName)\' 88 | trace '### QDF Warning, Please fix the duplication error else there might be issues'; 89 | endif 90 | LET vG.$(vL.ContainerPathName)$(vL.QDF.VariablePrefix)Path='$(vL.QDF.PhysicalFolderName)\'; 91 | // Writing information in log 92 | trace '### QDF Info, Created Global Variable vG.$(vL.ContainerPathName)$(vL.QDF.VariablePrefix)Path'; 93 | endif 94 | next vL.QDF.SubString; 95 | next vL.QDF.ttttt 96 | 97 | 98 | // Trim pace and last \ 99 | if right('$(vL.QDF.BasePath)',1)='\' then 100 | let vL.QDF.BasePath=left(trim('$(vL.QDF.BasePath)'), len('$(vL.QDF.BasePath)')-1); 101 | endif 102 | 103 | if '$(vL.QDF.SingleFolder)' ='' then // If SingleFolder not used add global vG.xxBasePath variable among the others 104 | LET vG.$(vL.ContainerPathName)BasePath='$(vL.QDF.BasePath)'; 105 | endif 106 | 107 | drop table [vL.DoDir_Tmp_Table]; // Drop DoDir tmp table 108 | trace '### QDF Info, DynamicContainerGlobalVariables Finished'; 109 | 110 | else 111 | trace '### QDF Warning, unable to identify DoDir table, probably no valid folder exists'; 112 | endif 113 | 114 | else 115 | trace '### QDF Info, Could not find $(vL.ContainerPathName) container in Container Map'; 116 | endif; 117 | 118 | // Clean Variables 119 | SET vL.QDF.ttttt = ; 120 | SET vL.QDF.xxxxx = ; 121 | SET vL.QDF.ContainerName=; 122 | SET vL.QDF.ContainerMapPath=; 123 | SET vL.QDF.SingleFolder=; 124 | SET vL.QDF.BasePath=; 125 | SET vL.ContainerFolderName=; 126 | SET vL.QDF.PhysicalFolderName=; 127 | SET vL.QDF.VariablePrefix=; 128 | SET vL.ContainerPathName=; 129 | SET vL.RootPath=; 130 | SET vL.Comment=; 131 | SET vL.QDF.SingleFolder=; 132 | SET vL.QDF.SubStringSplitt=; 133 | SET vL.QDF.SubString=; 134 | SET vL.QDF.DuplicatedFolders=; 135 | SET vL.QDF.OverridePrefix=; 136 | endsub 137 | 138 | // Sub Function short name for DynamicContainerGlobalVariables = DCGV 139 | SUB DCGV(vL.QDF.ContainerName_tmp,vL.QDF.SingleFolder_tmp,vL.QDF.OverridePrefix_tmp); // Alias for LoadContainerGlobalVariables 140 | call DynamicContainerGlobalVariables('$(vL.QDF.ContainerName_tmp)','$(vL.QDF.SingleFolder_tmp)','$(vL.QDF.OverridePrefix_tmp)'); 141 | 142 | // Clean Variables 143 | SET vL.QDF.ContainerName_tmp=; 144 | SET vL.QDF.SingleFolder_tmp=; 145 | SET vL.QDF.OverridePrefix_tmp=; 146 | end sub 147 | 148 | 149 | // ************************************* 150 | // Functions written by Magnus Berg Qlik 151 | // ************************************* -------------------------------------------------------------------------------- /3.Include/4.Sub/3.LoadContainerMap.qvs: -------------------------------------------------------------------------------- 1 | // ____________________________________________________________________________ 2 | // SUB routine loading csv Container Map into a QlikView Script, is primarily used by 4.GenericContainerLoader.qvs 3 | // Execute (Call) the Sub in the script by first include the script in the beginning and then use: 4 | // call LoadContainerMap('container map csv', 'Name of Container to link'[,'Optional, retrive Root Path by typing current container name']); 5 | // Container base Variables will be loaded based on ContainerMap.csv 6 | // will return vL.ContainerPathName vL.ContainerFolderName vL.Comment vL.RootPath 7 | 8 | SUB LoadContainerMap(vL.QDF.CVSTableName,vL.QDF.SpecificVariable,vL.QDF.GetRootPath); 9 | 10 | //Reset vL.LoadContainerMapCount variable used to identify if two or more identical Variable Prefix exist 11 | SET vL.LoadContainerMapCount=; 12 | SET vL.QDF.ValidatedBasePath=; 13 | 14 | if not '$(vL.QDF.GetRootPath)'='' then // If GetRootPath switsh activated find input base and relative path 15 | // Remove double backslash 16 | if index(trim('$(vL.QDF.GetRootPath)'),'\\',-1)>2 then // Remove double \\ in path, except in the beginning used in UNC path 17 | LET vL.QDF.GetRootPath=left( '$(vL.QDF.GetRootPath)' , (index( '$(vL.QDF.GetRootPath)', '\\', -1 )-1))&right('$(vL.QDF.GetRootPath)', (len( '$(vL.QDF.GetRootPath)' ) -index( '$(vL.QDF.GetRootPath)', '\\', -1 ))); 18 | endif 19 | 20 | let vL.QDF.To_Loop = substringcount ('$(vL.QDF.GetRootPath)' , '\') + substringcount ('$(vL.QDF.GetRootPath)' , '/'); // Count sub-folders for QlikView and Qlik Sense LIB folders 21 | 22 | for vL.QDF.From_Loop = vL.QDF.To_Loop to 1 step -1 23 | 24 | if filesize(left( '$(vL.QDF.GetRootPath)' , findoneof('$(vL.QDF.GetRootPath)' , '\/',vL.QDF.From_Loop) )&'InitLink.qvs') >0 then 25 | LET vL.QDF.ValidatedBasePath=left( '$(vL.QDF.GetRootPath)' , findoneof('$(vL.QDF.GetRootPath)' , '\/',vL.QDF.From_Loop)); //Found BasePath 26 | LET vL.RelativePath=mid('$(vL.QDF.GetRootPath)' , findoneof('$(vL.QDF.GetRootPath)' , '\/',vL.QDF.From_Loop)+1,len('$(vL.QDF.GetRootPath)')); //Relative Path in Container 27 | endif 28 | exit for when not '$(vL.QDF.ValidatedBasePath)'=''; 29 | next 30 | endif 31 | 32 | // Setting the correct ContainerMap.csv path 33 | if FileSize('$(vL.QDF.CVSTableName)') > 0 then 34 | Let vL.QDF.ContainerMapPath='$(vL.QDF.CVSTableName)'; 35 | else 36 | Let vL.QDF.ContainerMapPath='$(vG.BaseVariablePath)\ContainerMap.csv'; 37 | endif 38 | 39 | // Loading Container Map csv table as vL.temp_table_map 40 | unqualify ContainerPathName,Prefix,ContainerPathNameCount ; 41 | vL.temp_table_map: 42 | REPLACE LOAD * 43 | FROM 44 | '$(vL.QDF.ContainerMapPath)' 45 | (txt, utf8, embedded labels, delimiter is ',', msq); 46 | 47 | LET vL.ContainerPathName = FieldName(1,'vL.temp_table_map'); // ContainerPathName variable field (Tag) 48 | 49 | // count(ContainerPathName) to find if more than one ContainerPathName is used 50 | REPLACE Left join 51 | Load $(vL.ContainerPathName),count($(vL.ContainerPathName)) as ContainerPathNameCount 52 | Resident vL.temp_table_map 53 | group by $(vL.ContainerPathName); 54 | 55 | // loop through CSV table entries in search for LET and SET expresion 56 | let vL.QDF.To_Loop = NoOfRows('vL.temp_table_map'); 57 | 58 | for vL.QDF.From_Loop = 0 to vL.QDF.To_Loop-1 59 | 60 | LET vL.Comment =''; //reset comment entries 61 | 62 | LET vL.ContainerPathName = PurgeChar(trim(peek(FieldName(1,'vL.temp_table_map'),$(vL.QDF.From_Loop),'vL.temp_table_map')),'=;,- '&chr(39)); // ContainerPathName variable field (Tag) 63 | LET vL.ContainerFolderName = lower(PurgeChar(trim(peek(FieldName(2,'vL.temp_table_map'),$(vL.QDF.From_Loop),'vL.temp_table_map')),'=;,'&chr(39))); // ContainerFolderName field 64 | LET vL.Comment = PurgeChar(trim(peek(FieldName(3,'vL.temp_table_map'),$(vL.QDF.From_Loop),'vL.temp_table_map')),';,'&chr(39)); // Comment Field 65 | LET vL.RootPath = lower(PurgeChar(trim(peek(FieldName(4,'vL.temp_table_map'),$(vL.QDF.From_Loop),'vL.temp_table_map')),'=;,'&chr(39))); // RootPath other than default 66 | LET vL.QDF.ContainerPathNameCount = peek(FieldName(5,'vL.temp_table_map'),$(vL.QDF.From_Loop),'vL.temp_table_map'); 67 | 68 | // Do not do anything if row is empty 69 | if not '$(vL.ContainerPathName)' = '' and not '$(vL.ContainerFolderName)' = '' then 70 | 71 | // Correct \ if not exist 72 | if not right( '$(vL.ContainerFolderName)' , 1 ) ='\' then 73 | let vL.QDF.ContainerName_tmp ='$(vL.ContainerFolderName)'&'\'; 74 | else 75 | let vL.QDF.ContainerName_tmp ='$(vL.ContainerFolderName)'; 76 | endif; 77 | 78 | if left(trim('$(vL.RootPath)'),2) ='\\' or index('$(vL.RootPath)', ':')>0 then // If vL.AltRootPath have a valid path 79 | 80 | if not right('$(vL.RootPath)' , 1 ) ='\' then // Check and add '\' in root path 81 | let vL.RootPath ='$(vL.RootPath)'&'\'; 82 | endif; 83 | else 84 | let vL.RootPath ='$(vG.RootPath)'; 85 | endif; 86 | 87 | // Special Switch to find vG.RootPath used by 1.Init during initiation process 88 | // Will also identify current container (vL.ContainerPathName) 89 | if not '$(vL.QDF.ValidatedBasePath)'='' and substringcount(lower(left('$(vL.QDF.ValidatedBasePath)',len('$(vL.QDF.ValidatedBasePath)')-1)),lower(left('$(vL.RootPath)$(vL.QDF.ContainerName_tmp)',len('$(vL.RootPath)$(vL.QDF.ContainerName_tmp)')-1))) >0 then 90 | 91 | LET vL.RootPath= left('$(vL.QDF.ValidatedBasePath)',len('$(vL.QDF.ValidatedBasePath)')-(len('$(vL.QDF.ContainerName_tmp)'))); 92 | $(Include=$(vG.SubPath)\1.FileExist.qvs); 93 | call vL.FileExist ('$(vL.RootPath)$(vL.QDF.ContainerName_tmp)'); //validate that rootpath is correct 94 | if vL.FileExist = 'true' then 95 | LET vG.RootPath= '$(vL.RootPath)'; // Set new vG.RootPath 96 | Trace '### QDF Info, Creating vG.RootPath based on Container Map'; 97 | SET vL.QDF.Exit='True'; // When root path is set exit script 98 | endif 99 | elseif not '$(vL.QDF.ValidatedBasePath)'='' and lower('$(vL.QDF.ValidatedBasePath)')=lower('lib://$(vL.ContainerPathName)/') then //Current Container validation for Qlik Sense 100 | SET vL.QDF.Exit='True'; // When root path is set exit script 101 | endif 102 | 103 | 104 | // Finding vL.QDF.SpecificVariable and return values from Container Map 105 | if ('$(vL.QDF.SpecificVariable)'='$(vL.ContainerPathName)' or '$(vL.QDF.SpecificVariable)'='$(vL.ContainerFolderName)') then 106 | 107 | 108 | if vL.QDF.ContainerPathNameCount = 1 then // If only one container Path exists then exit 109 | SET vL.QDF.Exit= 'True'; // Exit For Loop 110 | 111 | else // Several container Path exists, send error message 112 | Trace '### QDF Warning, found duplication of $(vL.ContainerPathName), please correct'; 113 | //Reset vL.LoadContainerMapCount variable used to identify if two or more identical Variable Prefix exist 114 | SET vL.LoadContainerMapCount='$(vL.ContainerPathName)'; 115 | Sleep 5000; SET 5000=; // Remove variable 5000 created when running sleep!? 116 | SET vL.QDF.Exit= 'True'; // Exit For Loop 117 | endif 118 | exit for when '$(vL.QDF.Exit)'='True'; 119 | endif; 120 | exit for when '$(vL.QDF.Exit)'='True'; 121 | endif; 122 | next; 123 | 124 | drop table 'vL.temp_table_map'; // Dropping CSV Table after variables been read into the QlikView application 125 | 126 | //Resetting variables 127 | SET vL.QDF.From_Loop = ; 128 | SET vL.QDF.To_Loop = ; 129 | SET vL.QDF.CVSTableName = ; 130 | SET vL.QDF.SpecificVariable = ; 131 | SET vL.QDF.GetRootPath = ; 132 | SET vL.QDF.Exit= ; 133 | SET vL.QDF.ContainerName_tmp= ; 134 | SET vL.QDF.ContainerPathNameCount= ; 135 | SET vL.QDF.ValidatedBasePath=; 136 | SET vL.QDF.ContainerMapPath=; 137 | end sub 138 | 139 | // ********************************** 140 | // Function written by Magnus Berg 141 | // QlikView International AB 142 | // ********************************** -------------------------------------------------------------------------------- /3.Include/4.Sub/8.QVFileInfo.qvs: -------------------------------------------------------------------------------- 1 | // ___________________________________________________________________________ 2 | // Deployment Framework QVFileInfo sub function 8.QVFileInfo.qvs 3 | // 4 | // This script will collect the tables and fields from the QVW and QVD files 5 | // Fully Qualified file Name is the path and name of qvd or qvw file 6 | // Table Name (Optional) is name of the table returning the result 7 | // default table name is QVFileInfo linked with QVFileInfo_field (field details table) 8 | // First include the QVFileInfo Function $(Include=$(vG.SubPath)\8.QVFileInfo.qvs); 9 | // Usage QVFileInfo( 'Fully Qualified file Name',['Table Name']) 10 | // Example: QVFileInfo('$(vG.QVDPath)\Customer.qvd') 11 | // Example: QVFileInfo('$(vG.QVDPath)\Customer.qvd','QVFileTable') 12 | // 13 | // QVFileInfo works together with 5.DoDir.qvs 14 | // the field FullyQualifiedName will automatically link with DoDir result table 15 | // ___________________________________________________________________________ 16 | 17 | SUB QVFileInfo(vL.QDF.QVFile,vL.QDF.QVTableName); 18 | 19 | 20 | if FileTime('$(vL.QDF.QVFile)') > 0 then // Check if file exists 21 | 22 | // Remove double \\ in path, except in the beginning used in UNC path 23 | if index(trim('$(vL.QDF.QVFile)'),'\\',-1)>2 then 24 | LET vL.QDF.QVFile=left( '$(vL.QDF.QVFile)' , (index( '$(vL.QDF.QVFile)', '\\', -1 )-1))&right('$(vL.QDF.QVFile)', (len( '$(vL.QDF.QVFile)' ) -index( '$(vL.QDF.QVFile)', '\\', -1 ))); 25 | endif 26 | 27 | 28 | if '$(vL.QDF.QVTableName)'='' then // If No TableName Exists Use QVFileInfo 29 | SET vL.QDF.QVTableName = 'QVFileInfo'; 30 | endif; 31 | 32 | FOR Each vL.QDF.filelist in filelist ('$(vL.QDF.QVFile)') //when scanning multiple (*) QV files 33 | 34 | unqualify QVType,QVFormat,QVTablesKey,FullyQualifiedName,QVTableName,QVFileTime,QVTableNbrRows,QVTableNbrFields,QVTableNbrKeyFields,QVTableComment,QVFileName,QVFieldName,QVTableCreator,QVComment,QVTableCreator; 35 | 36 | switch upper(subfield('$(vL.QDF.filelist)','.',-1)); 37 | case 'QVW'; // Case QVW files is identified 38 | Let vL.QDF.QVTimeStamp =DATE(FileTime( '$(vL.QDF.filelist)' ),'YYYY-MM-DD') ; 39 | //SET ErrorMode =0; // remove error used if xml header can't be read 40 | [$(vL.QDF.QVTableName)]: 41 | LOAD 42 | upper('$(vL.QDF.filelist)' & '_' & '$(vL.QDF.QVTimeStamp)' &'_' & Name) as QVTablesKey, 43 | '$(vL.QDF.filelist)' as FullyQualifiedName, 44 | Name as QVTableName, 45 | timestamp(FileTime( '$(vL.QDF.filelist)') ,'$(TimestampFormat)') as QVFileTime, 46 | NoOfRows as QVTableNbrRows, 47 | NoOfFields as QVTableNbrFields, 48 | NoOfKeyFields as QVTableNbrKeyFields, 49 | Comment as QVTableComment, 50 | subfield('$(vL.QDF.filelist)','\',-1) as QVFileName, 51 | Null() as QVTableCreator // not used by QVW 52 | FROM $(vL.QDF.filelist) (XmlSimple, Table is [DocumentSummary/TableDescription]) //Load data from xml qvw header 53 | WHERE IsSystem = 'false'; 54 | if ScriptError <> 0 then // Error message if XML read goes wrong 55 | trace '### DF Error reading QVW XML Header, QVFileInfo '; 56 | trace '### DF File $(vL.QDF.filelist)'; 57 | endif 58 | 59 | [$(vL.QDF.QVTableName)_Fields]: 60 | LOAD 61 | upper('$(vL.QDF.filelist)' & '_' & '$(vL.QDF.QVTimeStamp)' &'_' & [SrcTables/String]) as QVTablesKey, 62 | Name as QVFieldName, 63 | QVComment 64 | FROM [$(vL.QDF.filelist)] (XmlSimple, Table is [DocumentSummary/FieldDescription]); 65 | WHERE IsSystem = 'false'; 66 | if ScriptError <> 0 then // Error message if XML read goes wrong 67 | trace '### DF Error reading QVW XML Header, 8.QVFileInfo.qvs '; 68 | trace '### DF File $(vL.QDF.filelist)'; 69 | endif 70 | SET ErrorMode =1; 71 | case 'QVD'; // Case QVD files is identified 72 | if QvdNoOfFields('$(vL.QDF.filelist)') > 0 then // no point in loading if the file is empty or have faulty 73 | 74 | // Validating compatible QVD's 75 | set ErrorMode=0; 76 | 77 | [$(vL.QDF.QVTableName)_Validate]: 78 | LOAD 79 | [CreatorDoc] as QVTableCreator 80 | FROM [$(vL.QDF.filelist)] (XmlSimple, Table is [QvdTableHeader]); 81 | 82 | if not ScriptError=0 then 83 | set vL.QDF.IncompatibleQVD=1; 84 | else 85 | set vL.QDF.IncompatibleQVD=; 86 | drop table [$(vL.QDF.QVTableName)_Validate]; 87 | endif 88 | set ErrorMode=1; 89 | 90 | if vL.QDF.IncompatibleQVD=1 then // Different load depending on QVD compatibility 91 | trace '### DF Found Incompatible QVD header format, will skip XML data'; 92 | 93 | [$(vL.QDF.QVTableName)]: 94 | LOAD 95 | upper('$(vL.QDF.filelist)' & '_' & Date(QvdCreateTime('$(vL.QDF.filelist)'),'YYYY-MM-DD') &'_' & QvdTableName('$(vL.QDF.filelist)')) as QVTablesKey, 96 | '$(vL.QDF.filelist)' as FullyQualifiedName, 97 | QvdTableName('$(vL.QDF.filelist)') as QVTableName, 98 | timestamp(QvdCreateTime('$(vL.QDF.filelist)'),'$(TimestampFormat)') as QVFileTime, 99 | QvdNoOfRecords('$(vL.QDF.filelist)') as QVTableNbrRows, 100 | QvdNoOfFields('$(vL.QDF.filelist)') as QVTableNbrFields, 101 | null() as QVTableNbrKeyFields, // not used by QVD 102 | null() as QVTableComment, // not used, QVD incompatibility 103 | subfield(replace('$(vL.QDF.filelist)','/','\'),'\',-1) as QVFileName, 104 | null() as QVTableCreator // not used, QVD incompatibility 105 | AUTOGENERATE(1); 106 | 107 | for vL.QDF.FieldNo = 1 to QvdNoOfFields('$(vL.QDF.filelist)') 108 | [$(vL.QDF.QVTableName)_Fields]: 109 | LOAD 110 | upper('$(vL.QDF.filelist)' & '_' & Date(QvdCreateTime('$(vL.QDF.filelist)'),'YYYY-MM-DD') &'_' & QvdTableName('$(vL.QDF.filelist)')) as QVTablesKey , 111 | QvdFieldName('$(vL.QDF.filelist)' , $(vL.QDF.FieldNo)) as QVFieldName, 112 | null() as QVComment // not used 113 | autogenerate 1; 114 | Next vL.QDF.FieldNo 115 | 116 | else 117 | [$(vL.QDF.QVTableName)]: 118 | LOAD 119 | upper('$(vL.QDF.filelist)' & '_' & Date(QvdCreateTime('$(vL.QDF.filelist)'),'YYYY-MM-DD') &'_' & QvdTableName('$(vL.QDF.filelist)')) as QVTablesKey, 120 | '$(vL.QDF.filelist)' as FullyQualifiedName, 121 | QvdTableName('$(vL.QDF.filelist)') as QVTableName, 122 | timestamp(QvdCreateTime('$(vL.QDF.filelist)'),'$(TimestampFormat)') as QVFileTime, 123 | QvdNoOfRecords('$(vL.QDF.filelist)') as QVTableNbrRows, 124 | QvdNoOfFields('$(vL.QDF.filelist)') as QVTableNbrFields, 125 | null() as QVTableNbrKeyFields, // not used by QVD 126 | [Comment] as QVTableComment, 127 | subfield(replace('$(vL.QDF.filelist)','/','\'),'\',-1) as QVFileName, 128 | [CreatorDoc] as QVTableCreator 129 | FROM [$(vL.QDF.filelist)] (XmlSimple, Table is [QvdTableHeader]); 130 | 131 | [$(vL.QDF.QVTableName)_Fields]: 132 | LOAD [FieldName] as QVFieldName, 133 | left([NumberFormat/Type],1) as QVType, // Keep only first letter as new QVD format only use first letter 134 | [NumberFormat/Fmt] as QVFormat, 135 | [Comment] as QVComment, 136 | upper('$(vL.QDF.filelist)' & '_' & Date(QvdCreateTime('$(vL.QDF.filelist)'),'YYYY-MM-DD') &'_' & QvdTableName('$(vL.QDF.filelist)')) as QVTablesKey 137 | FROM [$(vL.QDF.filelist)] (XmlSimple, Table is [QvdTableHeader/Fields/QvdFieldHeader]); 138 | endif 139 | 140 | else 141 | trace '### DF Info 8.QVFileInfo.qvs Cant find any data in $(vL.QDF.QVFile)'; 142 | endif 143 | 144 | end switch 145 | 146 | next vL.QDF.filelist 147 | 148 | // ----------------------------------------------- 149 | // Comment section for the table and its fields 150 | // ----------------------------------------------- 151 | comment Field QVTablesKey with 'This field is a combination of the file name and table name of the QVW table.'; 152 | comment Field FullyQualifiedName with 'Fully Qualified Name of QlikView File.'; 153 | comment Field QVTableName with 'Table name of the QVW table scanned'; 154 | comment Field QVTableNbrRows with 'Number of rows in the QVW table.'; 155 | comment Field QVTableNbrFields with 'Number of fields in the QVW table.'; 156 | comment Field QVTableNbrKeyFields with 'Number of key fields in the QVW table.'; 157 | comment Field QVTableComment with 'Table comment in the QVW table (loaded in the script).'; 158 | 159 | 160 | comment Field QVTablesKey with 'This field is a combination of the file name and table name of the QVW table.'; 161 | comment Field QVFieldName with 'QVW Field name in the QVW table that was scanned.'; 162 | comment Field QVWComment with 'Comment for the field (loaded in the script).'; 163 | else 164 | trace '### DF Info 8.QVWInfo.qvs Cant find $(vL.QDF.QVFile)'; 165 | endif 166 | 167 | // Clean up 168 | SET vL.QDF.QVFile=; 169 | SET vL.QDF.QVTableName=; 170 | SET vL.QDF.QVTimeStamp=; 171 | SET vL.QDF.FieldNo=; 172 | SET vL.QDF.filelist=; 173 | set vL.QDF.IncompatibleQVD=; 174 | 175 | END SUB 176 | 177 | // ************************************* 178 | // Functions written by Magnus Berg Qlik 179 | // ************************************* -------------------------------------------------------------------------------- /3.Include/4.Sub/9.QVDMigration.qvs: -------------------------------------------------------------------------------- 1 | // ___________________________________________________________________________ 2 | // Deployment Framework QVDMigration sub function 9.QVDMigration.qvs 3 | // 4 | // Returns a Table containing files and path in selected file system (vL.DoDirRoot) 5 | // First include the QVDMigration Function $(Include=$(vG.SubPath)\9.QVDMigration.qvs); 6 | // Use the function QVDMigration to execute. examples: 7 | // call QVDMigration (vL.QDF.MigrationSource,vL.QDF.MigrationDestination, vL.QDF.Store_Select); //Simple Example 8 | // call QVDMigration ('$(vG.QVDPath)\Customer.qvd','$(vG.SharedQVDPath)\Customer.qvd', 'CustomerID,CompanyName'); 9 | 10 | sub QVDMigration (vL.QDF.MigrationSource,vL.QDF.MigrationDestination,vL.QDF.Store_Select,vL.QDF.Scramble_fields,vL.QDF.QVTableName_Suffix,vL.QDF.IncludeSubFolders,vL.QDF.FormatSpec,vL.QDF.NoRecords) 11 | 12 | call vL.FileExist('$(vL.QDF.MigrationSource)'); // Check if folder or file exist 13 | if vL.FileExist = 'true' then 14 | 15 | // Migrate data to other formats then qvd 16 | if trim(lower('$(vL.QDF.FormatSpec)'))='txt' or trim(lower('$(vL.QDF.FormatSpec)'))='qvx' then 17 | let vL.QDF.FormatSpec=trim(lower('$(vL.QDF.FormatSpec)')); //Create format-spec that will be in the Store statement 18 | else 19 | let vL.QDF.FormatSpec='qvd'; 20 | endif 21 | 22 | if '$(vL.QDF.Store_Select)'='' or vL.QDF.Store_Select=null then // If no specific fields selected use * 23 | SET vL.QDF.Store_Select = '*'; 24 | else 25 | LET vL.QDF.Store_Select=Replace(Replace(','&'$(vL.QDF.Store_Select)'&',',' ,',','),', ',',');// Adding (,) to identify fields in loop, uses (,) as field separators and remove unwanted spaces 26 | end if 27 | 28 | LET vL.QDF.Scramble_fields=','&'$(vL.QDF.Scramble_fields)'&','; // Adding (,) to identify fields in loop, uses (,) as field separators 29 | 30 | if lower('$(vL.QDF.IncludeSubFolders)')='true' then // Change vL.QDF.IncludeSubFolders = true to false to parse into DoDir use single folder (default multiple folders) 31 | let vL.QDF.IncludeSubFolders=''; 32 | else 33 | let vL.QDF.IncludeSubFolders='true'; 34 | endif 35 | 36 | //Limit amount of records 37 | if vL.QDF.NoRecords > 0 then 38 | let vL.QDF.NoRecords = 'First $(vL.QDF.NoRecords)'; 39 | else 40 | let vL.QDF.NoRecords=; 41 | endif 42 | 43 | switch upper(subfield(trim('$(vL.QDF.MigrationSource)'),'\',-1)) // change vL.QDF.MigrationSource depending on how users write 44 | case '' 45 | let vL.QDF.MigrationSource= trim('$(vL.QDF.MigrationSource)')&'*.qvd'; 46 | case '*' 47 | let vL.QDF.MigrationSource= trim('$(vL.QDF.MigrationSource)')&'.qvd'; 48 | default 49 | end switch 50 | 51 | call DoDir ('$(vL.QDF.MigrationSource)','__vL.DoDir_TMP','','$(vL.QDF.IncludeSubFolders)','true'); // Cal DoDir sub function 52 | 53 | if NoOfFields('__vL.DoDir_TMP') > 0 then // if no fields exist (no qvd files) do not continue 54 | 55 | for vL.QDF.DirList_tmp = 0 to (NoOfRows('__vL.DoDir_TMP'))-1 56 | 57 | LET vL.QDF.filelist_tmp = trim(peek(FieldName(2,'__vL.DoDir_TMP'),$(vL.QDF.DirList_tmp),'__vL.DoDir_TMP')); // Peek qvd files 58 | exit for when '$(vL.QDF.filelist_tmp)' = ''; 59 | // Reset vL.QDF.Store_Select_new variable 60 | SET vL.QDF.Store_Select_new=; 61 | 62 | call QVFileInfo ('$(vL.QDF.filelist_tmp)','__vL.FileInfo_TMP'); // get QVD file info into table __vL.FileInfo_TMP and __vL.FileInfo_TMP_Fields 63 | 64 | LET vL.QDF.QVTableName=subfield(peek('QVTableName',0,'__vL.FileInfo_TMP'),'\',-1); 65 | LET vL.QDF.QVDTag = peek('QVTableComment',0,'__vL.FileInfo_TMP'); 66 | 67 | if not '$(vL.QDF.QVTableName)' = '' then 68 | 69 | for vL.QDF.NoOfRows_Loop = 0 to (NoOfRows('__vL.FileInfo_TMP_Fields')-1) 70 | 71 | LET vL.QDF.TempField = trim(peek('QVFieldName',$(vL.QDF.NoOfRows_Loop),'__vL.FileInfo_TMP_Fields')); 72 | LET vL.QDF.TempField_new = ','&'$(vL.QDF.TempField)'&','; // used to identify fields in loop, uses (,) as field separators 73 | 74 | 75 | switch '$(vL.QDF.TempField_new)' //Change scramble field based on vL.SubString 76 | case mid('$(vL.QDF.Scramble_fields)', index('$(vL.QDF.Scramble_fields)' , '$(vL.QDF.TempField_new)'), len('$(vL.QDF.TempField_new)')); 77 | LET vL.QDF.Store_Select_new='$(vL.QDF.Store_Select_new)' & ' If(IsNum([$(vL.QDF.TempField)]),Left(autonumberhash128([$(vL.QDF.TempField)])*Len($(vL.QDF.TempField))*ceil(rand()*10,2),Len($(vL.QDF.TempField))), Left(hash128(['&'$(vL.QDF.TempField)'&'],$(vL.NoOfRows_Loop_tmp)),Len($(vL.QDF.TempField)))) as ['&'$(vL.QDF.TempField)], '; // concat query, FPN 78 | 79 | case mid('$(vL.QDF.Store_Select)', index('$(vL.QDF.Store_Select)' , '$(vL.QDF.TempField_new)'), len('$(vL.QDF.TempField_new)')); 80 | LET vL.QDF.Store_Select_new='$(vL.QDF.Store_Select_new)' & '[$(vL.QDF.TempField)],'; // Concatenated statement 81 | default 82 | if vL.QDF.Store_Select = '*' then 83 | LET vL.QDF.Store_Select_new='$(vL.QDF.Store_Select_new)' & '[$(vL.QDF.TempField)],'; // Concatenated statement 84 | endif 85 | end switch 86 | 87 | next vL.QDF.NoOfRows_Loop 88 | 89 | 90 | // Remove (,) in back of the lastconcatenated statement 91 | LET vL.QDF.Store_Select_new= left(trim('$(vL.QDF.Store_Select_new)'),(len( trim('$(vL.QDF.Store_Select_new)'))-1 )); 92 | 93 | if not '$(vL.QDF.Store_Select_new)' ='' then 94 | [$(vL.QDF.QVTableName)$(vL.QDF.QVTableName_Suffix)]: // Load QVD file based on vL.QDF.Store_Select_new concatenated statement 95 | $(vL.QDF.NoRecords) 96 | LOAD $(vL.QDF.Store_Select_new) 97 | FROM '$(vL.QDF.filelist_tmp)' 98 | (qvd); 99 | 100 | if not '$(vL.QDF.MigrationDestination)' = '' then 101 | 102 | if lower(subfield('$(vL.QDF.MigrationDestination)','.',-1))='$(vL.QDF.FormatSpec)' then //Check QVD, qvx, txt destination file, if non existing use same as source 103 | let vL.QDF.MigrationDestination_tmp='$(vL.QDF.MigrationDestination)'; 104 | trace '### DF 9.QVDMigration.qvs will migrate to a single qvd file due to no trailing \ at destination path, files could be overwritten'; 105 | else 106 | // Identify Source qvd name and path and parse with destination path 107 | LET vL.QDF.MigrationDestination_tmp=trim('$(vL.QDF.MigrationDestination)\'& mid('$(vL.QDF.filelist_tmp)', len(left ('$(vL.QDF.MigrationSource)',index('$(vL.QDF.MigrationSource)','\',-1))))); 108 | LET vL.QDF.MigrationDestination_tmp=left('$(vL.QDF.MigrationDestination_tmp)',(len('$(vL.QDF.MigrationDestination_tmp)')-4))&'.$(vL.QDF.FormatSpec)'; // Create correct file extension 109 | endif 110 | 111 | 112 | LET vL.QDF.FolderPath_tmp= left ('$(vL.QDF.MigrationDestination_tmp)',index('$(vL.QDF.MigrationDestination_tmp)','\',-1)); // Remove qvd file name to get folder names only 113 | $(Include=$(vG.SubPath)\6.CreateFolder.qvs); 114 | call CreateFolder('$(vL.QDF.FolderPath_tmp)'); // Check if SubFolders it need to be created under destination folder 115 | 116 | if not '$(vL.QDF.QVDTag)'='' or not '$(vL.QDF.QVTableName_Suffix)'='' then //Transfer tags from source qvd + add suffix as tag 117 | comment table [$(vL.QDF.QVTableName)$(vL.QDF.QVTableName_Suffix)] with ',$(vL.QDF.QVDTag),$(vL.QDF.QVTableName_Suffix),' ; // add meta-tags 118 | endif 119 | 120 | Store * from [$(vL.QDF.QVTableName)$(vL.QDF.QVTableName_Suffix)] into '$(vL.QDF.MigrationDestination_tmp)' ($(vL.QDF.FormatSpec)); 121 | drop table [$(vL.QDF.QVTableName)$(vL.QDF.QVTableName_Suffix)]; 122 | endif 123 | 124 | drop table __vL.FileInfo_TMP,__vL.FileInfo_TMP_Fields; 125 | endif 126 | 127 | else 128 | trace '### DF Warning 9.QVDMigration.qvs not a valid qvd file $(vL.QDF.filelist_tmp)'; 129 | endif 130 | 131 | next vL.QDF.DirList_tmp 132 | drop table __vL.DoDir_TMP; 133 | 134 | else 135 | trace '### DF Warning 9.QVDMigration.qvs no qvd files found '; 136 | endif 137 | else 138 | trace '### DF Warning 9.QVDMigration.qvs Cant find File Paths or qvd Suffix'; 139 | end if 140 | SET vL.QDF.QVTableName_Suffix=; 141 | SET vL.QDF.NoRecords=; 142 | SET vL.QDF.QVTableName=; 143 | SET vL.QDF.MigrationSource=; 144 | SET vL.QDF.MigrationDestination=; 145 | SET vL.QDF.MigrationDestination_tmp=; 146 | SET vL.QDF.Store_Select=; 147 | SET vL.QDF.Store_Select_new=; 148 | SET vL.QDF.Scramble_fields=; 149 | SET vL.QDF.NoOfRows_Loop=; 150 | SET vL.QDF.filelist_tmp=; 151 | SET vL.QDF.TempField=; 152 | SET vL.QDF.TempField_new=; 153 | SET vL.QDF.IncludeSubFolders=; 154 | SET vL.QDF.DirList_tmp=; 155 | SET vL.QDF.FolderPath_tmp=; 156 | SET vL.QDF.FormatSpec=; 157 | end sub 158 | 159 | //___________________________________________________________________________ 160 | // Deployment Framework QVDLoad sub function 161 | // Loads up a data model based on QVD files in Source destination and the qvd Meta-data table name 162 | // QVDLoad is based on QVDMigration sub function only difference is that destination path is missing 163 | // First include the QVDLoad Function $(Include=$(vG.SubPath)\10.QVDLoad.qvs); 164 | // Use the function QVDLoad to execute. examples: 165 | // call QVDMigration (vL.QDF.MigrationSource,vL.MigrationDestination, vL.QDF.Store_Select); //Simple Example 166 | // call QVDMigration ('$(vG.QVDPath)\Customer.qvd','$(vG.SharedQVDPath)\Customer.qvd', 'CustomerID,CompanyName'); 167 | 168 | sub QVDLoad(vL.QDF.MigrationSource,vL.QDF.Store_Select,vL.QDF.Scramble_fields,vL.QDF.QVTableName_Suffix,vL.QDF.IncludeSubFolders,vL.QDF.NoRecords) 169 | call QVDMigration ('$(vL.QDF.MigrationSource)','','$(vL.QDF.Store_Select)','$(vL.QDF.Scramble_fields)','$(vL.QDF.QVTableName_Suffix)','$(vL.QDF.IncludeSubFolders)','','$(vL.QDF.NoRecords)'); 170 | 171 | SET vL.QDF.QVTableName_Suffix=; 172 | SET vL.QDF.MigrationSource=; 173 | SET vL.QDF.Store_Select=; 174 | SET vL.QDF.Scramble_fields=; 175 | SET vL.QDF.IncludeSubFolders=; 176 | set vL.QDF.NoRecords=; 177 | 178 | end sub 179 | 180 | // ************************************* 181 | // Functions written by Magnus Berg Qlik 182 | // ************************************* 183 | -------------------------------------------------------------------------------- /3.Include/4.Sub/2.LoadVariableCSV.qvs: -------------------------------------------------------------------------------- 1 | // ____________________________________________________________________________ 2 | // Qlik Deployment Framework SUBVariable 2.LoadVariableCSV.qvs 3 | // SUB routine used for loading variables stored in csv files into the QlikView Script 4 | // Execute (Call) the Sub in the script, by first include the script in the beginning: 5 | // $(Include=$(vG.SubPath)\2.LoadVariableCSV.qvs); 6 | // and then use: 7 | // call LoadVariableCSV('CSV_My Tables.csv', ,Optional vL.SpecificVariable or Tag, Optional vL.QDF.ContainerMapMode, Optional Use Comments as Variables, Optional Specify table name, will keep the table after load); 8 | // Mandatory switch is csv path and file 'CSV_My Tables.csv' 9 | // By using vL.QDF.ContainerMapMode the csv will be treated as an ContainerMap.csv file 10 | // And Container base Variables will be loaded based on ContainerMap.csv 11 | 12 | SUB LoadVariableCSV(vL.QDF.CVSTableName,vL.QDF.SpecificVariable,vL.QDF.ContainerName,vL.QDF.CommentsAsVariables,vL.QDF.ContainerMapMode); 13 | //$(Include=$(vG.SubPath)\1.FileExist.qvs); 14 | //$(Include=$(vG.SubPath)\5.DoDir.qvs); 15 | 16 | // Loading CSV table based on vL.QDF.CVSTableName variables. 17 | if not '$(vL.QDF.ContainerName)'='' and not 'vL.QDF.CVSTableName'='' then //If a container entry is used find this in the container map 18 | call LoadContainerGlobalVariables('$(vL.QDF.ContainerName)','BaseVariable'); 19 | call vL.FileExist ('$(vG.$(vL.QDF.ContainerName)BaseVariablePath)$(vL.QDF.CVSTableName)'); 20 | 21 | if vL.FileExist = 'true' then 22 | Let vL.QDF.CVSTableName='$(vG.$(vL.QDF.ContainerName)BaseVariablePath)$(vL.QDF.CVSTableName)'; 23 | endif 24 | 25 | elseif not 'vL.QDF.CVSTableName'='' then // If vL.QDF.ContainerName missing use standard folders 26 | 27 | call vL.FileExist ('$(vL.QDF.CVSTableName)'); 28 | 29 | if vL.FileExist = 'false' then // Try a second time using default vG.BaseVariablePath 30 | Let vL.QDF.CVSTableNameOrig='$(vL.QDF.CVSTableName)'; //this variable is used in Shared Lookup 31 | Let vL.QDF.CVSTableName='$(vG.BaseVariablePath)$(vL.QDF.CVSTableName)'; 32 | call vL.FileExist ('$(vL.QDF.CVSTableName)'); 33 | endif 34 | 35 | if vL.FileExist = 'false' then // Try a third time using shared vG.SharedBaseVariablePath 36 | Let vL.QDF.CVSTableName='$(vG.SharedBaseVariablePath)$(vL.QDF.CVSTableNameOrig)'; 37 | call vL.FileExist ('$(vL.QDF.CVSTableName)'); 38 | endif 39 | 40 | endif 41 | 42 | if not vL.FileExist = 'false' then 43 | 44 | if index('$(vL.QDF.CVSTableName)','.csv')=0 then // Add csv if missing 45 | Let vL.QDF.CVSTableName='$(vL.QDF.CVSTableName)*Variables.csv'; 46 | endif 47 | 48 | call DoDir('$(vL.QDF.CVSTableName)','QDF.DoDir_Tmp_Tbl','','true','true'); 49 | 50 | let vL.QDF.DoDir_Tmp_Tbl = NoOfRows('QDF.DoDir_Tmp_Tbl'); 51 | 52 | for vL.QDF.DoDir_Tmp_Tbl_2 = 0 to vL.QDF.DoDir_Tmp_Tbl-1 53 | 54 | LET vL.QDF.CVSTableName = peek('QDF.DoDir_Tmp_Tbl.FullyQualifiedName',$(vL.QDF.DoDir_Tmp_Tbl_2),'QDF.DoDir_Tmp_Tbl'); 55 | 56 | if index(lower('$(vL.QDF.CVSTableName)'),'_backup')=0 then // Do not load if it's a _Backup file 57 | 58 | //trace '### QDF Starting LoadVariableCSV'; 59 | 60 | [vL.temp_table]: 61 | 62 | REPLACE LOAD * 63 | FROM 64 | [$(vL.QDF.CVSTableName)] 65 | (txt, utf8, embedded labels, delimiter is ',', msq); 66 | 67 | //loop through CSV table entries in search for LET and SET expression 68 | let vL.QDF.To_loop = NoOfRows('vL.temp_table'); 69 | 70 | for vL.QDF.From_loop = 0 to vL.QDF.To_loop-1 71 | 72 | LET vL.QDF.VariableField = PurgeChar(trim(peek(FieldName(1,'vL.temp_table'),$(vL.QDF.From_loop),'vL.temp_table')),'=;,-"'&chr(39)); // Find variable field remove unused characters (=;) 73 | 74 | // If values are blank no point in going to Switch 75 | if not '$(vL.QDF.VariableField)'='' then 76 | 77 | LET vL.QDF.TableUpper = upper(trim(left('$(vL.QDF.VariableField)',4))); // Grab LET or SET commands from variable field 78 | LET vL.QDF.Variable = PurgeChar(subfield(trim('$(vL.QDF.VariableField)'), ' ' ,2),';,'&chr(39)); // Grab Variable from variable field 79 | LET vL.QDF.Commentfield = PurgeChar(peek(FieldName(3,'vL.temp_table'),$(vL.QDF.From_loop),'vL.temp_table'),';,'&chr(39)); // Load Comment Field, remove unused characters 80 | LET vL.QDF.Tag = ','&PurgeChar(trim(peek(FieldName(4,'vL.temp_table'),$(vL.QDF.From_loop),'vL.temp_table')),';'&chr(39))&','; // Load Tag Field remove unused characters 81 | 82 | 83 | // Validate if Tag is available 84 | if not trim('$(vL.QDF.SpecificVariable)') = '' then 85 | LET vL.QDF.TableUpper_tmp = '$(vL.QDF.TableUpper)'; 86 | LET vL.QDF.TableUpper='NoExecution' ; 87 | for vL.QDF.Tag_tmp = 0 to (substringcount('$(vL.QDF.Tag)',',')-2) 88 | LET vL.QDF.filelist_tmp=TextBetween('$(vL.QDF.Tag)', ',' , ',' , $(vL.QDF.Tag_tmp)+1 ); 89 | 90 | if substringcount(','&trim('$(vL.QDF.SpecificVariable)'&',') , ','&trim('$(vL.QDF.filelist_tmp)')&',')>0 then 91 | SET vL.QDF.TableUpper='$(vL.QDF.TableUpper_tmp)'; 92 | endif 93 | 94 | exit for when not '$(vL.QDF.TableUpper)' = 'NoExecution' // Reset vL.Store_Select_tmp_new variable 95 | next vL.QDF.Tag_tmp 96 | 97 | SET vL.QDF.Tag_tmp =; 98 | endif 99 | 100 | // Special tweaks for ContainerMapMode 101 | If upper('$(vL.QDF.ContainerMapMode)') = 'TRUE' then 102 | SET vL.QDF.TableUpper = 'ContainerMapMode'; // Changing to ContainerMapMode to execute in switch 103 | LET vL.QDF.Variable = 'vG.'&PurgeChar('$(vL.QDF.VariableField)',' ')&'BasePath'; // Creating BasePath Variables 104 | LET vL.QDF.Valuefield = PurgeChar(peek(FieldName(2,'vL.temp_table'),$(vL.QDF.From_loop),'vL.temp_table'),'=;",'&chr(39)); 105 | LET vL.QDF.AltRootFolderPath = peek(FieldName(4,'vL.temp_table'),$(vL.QDF.From_loop),'vL.temp_table'); // Root folder if other than default 106 | 107 | if left(trim('$(vL.QDF.AltRootFolderPath)'),2) ='\\' or index('$(vL.QDF.AltRootFolderPath)', ':')>0 then // change root to new path 108 | LET vL.RootPath = '$(vL.QDF.AltRootFolderPath)'; 109 | else 110 | LET vL.RootPath = '$(vG.RootPath)'; 111 | endif 112 | 113 | LET vL.QDF.Valuefield = '$(vL.RootPath)$(vL.QDF.Valuefield)\'; // Creating Container root path 114 | SET vL.QDF.TableUpper = 'ContainerMapMode'; // Changing to ContainerMapMode to execute in switch 115 | endif; 116 | 117 | 118 | // Check for SET or LET expressions 119 | switch '$(vL.QDF.TableUpper)' 120 | case 'LET' 121 | LET $(vL.QDF.Variable) = evaluate(peek(FieldName(2,'vL.temp_table'),$(vL.QDF.From_loop),'vL.temp_table')); // Evaluate LET variables 122 | if IsNull($(vL.QDF.Variable)) = -1 then // If evaluate do not work try other method 123 | LET $(vL.QDF.Variable) = peek(FieldName(2,'vL.temp_table'),$(vL.QDF.From_loop),'vL.temp_table'); // Executing SET variables 124 | endif 125 | //Use Comments as additional variable (_Comments prefix) 126 | if lower('$(vL.CommentsAsVariables)') ='true' or lower('$(vL.QDF.CommentsAsVariables)') ='true' then //Use Comments as additional variable (_Comments prefix) 127 | if not '$(vL.QDF.Commentfield)' ='' and not '$(vL.QDF.TableUpper)' = 'NoExecution' then // no point in creating a blank variable or variable execution not run 128 | LET $(vL.QDF.Variable)_Comments = PurgeChar(peek(FieldName(3,'vL.temp_table'),$(vL.QDF.From_loop),'vL.temp_table'),'=;'&chr(39)); 129 | endif 130 | endif 131 | case 'SET' 132 | LET $(vL.QDF.Variable) = peek(FieldName(2,'vL.temp_table'),$(vL.QDF.From_loop),'vL.temp_table'); // Executing SET variables 133 | //Use Comments as additional variable (_Comments prefix) 134 | if lower('$(vL.CommentsAsVariables)') ='true' or lower('$(vL.QDF.CommentsAsVariables)') ='true' then //Use Comments as additional variable (_Comments prefix) 135 | if not '$(vL.QDF.Commentfield)' ='' and not '$(vL.QDF.TableUpper)' = 'NoExecution' then // no point in creating a blank variable or variable execution not run 136 | LET $(vL.QDF.Variable)_Comments = PurgeChar(peek(FieldName(3,'vL.temp_table'),$(vL.QDF.From_loop),'vL.temp_table'),'=;'&chr(39)); 137 | endif 138 | endif 139 | case 'ContainerMapMode' 140 | SET $(vL.QDF.Variable) = '$(vL.QDF.Valuefield)'; // Executing SET variable in ContainerMapMode 141 | case 'NoExecution' 142 | // No Execution will be done, this is used when executing by a tag 143 | default 144 | LET $(vL.QDF.VariableField) = peek(FieldName(2,'vL.temp_table'),$(vL.QDF.From_loop),'vL.temp_table'); // Executing SET variables is SEt or LET not specified 145 | if lower('$(vL.CommentsAsVariables)') ='true' or lower('$(vL.QDF.CommentsAsVariables)') ='true' then //Use Comments as additional variable (_Comments prefix) 146 | if not '$(vL.QDF.Commentfield)' ='' and not '$(vL.QDF.TableUpper)' = 'NoExecution' then // no point in creating a blank variable or variable execution not run 147 | LET $(vL.QDF.VariableField)_Comments = PurgeChar(peek(FieldName(3,'vL.temp_table'),$(vL.QDF.From_loop),'vL.temp_table'),'=;'&chr(39)); 148 | endif 149 | endif 150 | end switch 151 | 152 | 153 | endif; 154 | 155 | SET vL.QDF.TableUpper = ; // Reset TableUpper after every iteration 156 | SET vL.QDF.TableUpper_tmp = ; 157 | 158 | SET vL.QDF.Commentfield =''; // Reset comment entries 159 | 160 | next vL.QDF.From_loop 161 | drop table 'vL.temp_table'; // Dropping CSV Table after variables been read into the QlikView application 162 | 163 | endif 164 | 165 | next vL.QDF.DoDir_Tmp_Tbl_2 166 | drop table 'QDF.DoDir_Tmp_Tbl'; // Dropping DoDir Table after variables been read into the QlikView application 167 | 168 | 169 | //Resetting variables 170 | SET vL.QDF.From_loop = ; 171 | SET vL.QDF.To_loop = ; 172 | SET vL.QDF.Tag =; 173 | SET vL.QDF.VariableField= ; 174 | SET vL.QDF.Variable = ; 175 | SET vL.QDF.Valuefield = ; 176 | SET vL.QDF.Commentfield = ; 177 | SET vL.QDF.AltRootFolderPath = ; 178 | SET vL.QDF.CVSTableName = ; 179 | SET vL.QDF.SpecificVariable = ; 180 | SET vL.QDF.ContainerMapMode = ; 181 | SET vL.QDF.CommentsAsVariables = ; 182 | SET vL.QDF.ContainerName = ; 183 | SET vL.QDF.DoDir_Tmp_Tbl = ; 184 | SET vL.QDF.DoDir_Tmp_Tbl_2 = ; 185 | SET vL.QDF.CVSTableNameOrig = ; 186 | SET vL.QDF.filelist_tmp = ; 187 | 188 | 189 | 190 | // Writing information in log 191 | trace '### QDF Info, LoadVariableCSV done'; 192 | else 193 | trace '### QDF Error, Did not find $(vL.QDF.CVSTableName), exit LoadVariableCSV'; 194 | endif; 195 | SET vL.FileExist = ; 196 | end sub 197 | 198 | 199 | // ********************************** 200 | // Function written by Magnus Berg 201 | // QlikView International AB 202 | // ********************************** -------------------------------------------------------------------------------- /3.Include/4.Sub/7.CalendarGen.qvs: -------------------------------------------------------------------------------- 1 | // ___________________________________________________________________________ 2 | // Calendar Generation Script 3 | // v1.0, 16-Sep-2008, Author: Jonas Valleskog 4 | // v2.0, 07-Dec-2012, Author: Jonas Valleskog 5 | // v3.0 23-Jan-2013, Authors: Finn Nordensjö, Magnus Berg 6 | // v3.1 05-Mar-2014, Author: Magnus Berg (minor fixes and added additional flags) 7 | // v3.2 2016, Author: Magnus Berg added native Qlik Sense calendar 8 | // v3.3 14-Jul-2022, Author: Mario Weigl (fixed issue 25 wrong year for week) 9 | // Notes: Generic calendar generation script that enables scalable handling of creating and navigating multiple date fields 10 | 11 | SUB CalendarGen(vL.QDF.DateFieldLinkName,vL.QDF.CalendarTableName,vL.QDF.MonthsLeftFiscalDates,vL.QDF.CalendarGenMinDateOrg,vL.QDF.CalendarGenMaxDateOrg,vL.QDF.DateFormatOrg); 12 | 13 | for vL.QDF.IndexFields_tmp = 0 to (substringcount(',$(vL.QDF.DateFieldLinkName),',',')-2) 14 | 15 | LET vL.QDF.DateFieldLinkName_new=trim(TextBetween(',$(vL.QDF.DateFieldLinkName),', ',' , ',' , $(vL.QDF.IndexFields_tmp)+1 )); 16 | 17 | 18 | if vL.QDF.IndexFields_tmp > 0 or '$(vL.QDF.CalendarTableName)' ='' then // if multiple fields are mode is used we need to autogenerate the maping calendar tablename 19 | Let vL.QDF.CalendarTableName = '$(vL.QDF.DateFieldLinkName_new)'; 20 | endif 21 | 22 | // ## Calendar format parsing Start 23 | LET vL.QDF.DateFormat_$(vL.QDF.IndexFields_tmp)=trim(TextBetween(',$(vL.QDF.DateFormatOrg),', ',' , ',' , $(vL.QDF.IndexFields_tmp)+1 )); 24 | 25 | 26 | if not '$(vL.QDF.DateFormat_$(vL.QDF.IndexFields_tmp))' ='' then //validate if dateformat avalible 27 | LET vL.QDF.DateFormat='$(vL.QDF.DateFormat_$(vL.QDF.IndexFields_tmp))'; 28 | let vL.QDF.DateFormat_old='$(vL.QDF.DateFormat)'; // set vL.QDF.IndexFields_old to current format number 29 | elseif not '$(vL.QDF.DateFormat_old)' ='' then // If dateformat missing try using previous 30 | LET vL.QDF.DateFormat='$(vL.QDF.DateFormat_old)'; 31 | else 32 | LET vL.QDF.DateFormat='$(DateFormat)'; //Use standard dateformat if speciffic format is missing 33 | endif 34 | 35 | // Clean older dateformat 36 | LET vL.QDF.DateFormat_$(vL.QDF.IndexFields_tmp)=; 37 | 38 | // if Min and Max set manual 39 | if not '$(vL.QDF.CalendarGenMinDateOrg)' = '' and not '$(vL.QDF.CalendarGenMaxDateOrg)' = '' then 40 | LET vL.QDF.CalendarGenMinDate = Num(Date(Date#('$(vL.QDF.CalendarGenMinDateOrg)','$(vL.QDF.DateFormat)'))) ; 41 | LET vL.QDF.CalendarGenMaxDate = Num(Date(Date#('$(vL.QDF.CalendarGenMaxDateOrg)','$(vL.QDF.DateFormat)'))) ; 42 | 43 | endif 44 | 45 | // if Min and Max set automatic or not working in manual 46 | if '$(vL.QDF.CalendarGenMinDate)' = '' or '$(vL.QDF.CalendarGenMaxDate)' = '' then 47 | 48 | CalendarGenMinMax: 49 | Load 50 | num(min(_DateMinMaxKey)) AS QDF.CalendarGenMinDate, //gets min date out of key date in the fact table 51 | num(max(_DateMinMaxKey)) AS QDF.CalendarGenMaxDate; //gets max date ou tof key date in the fact table 52 | Load FieldValue('$(vL.QDF.DateFieldLinkName_new)',IterNo()) as _DateMinMaxKey 53 | AutoGenerate(1) 54 | while not IsNull(FieldValue('$(vL.QDF.DateFieldLinkName_new)',IterNo())); 55 | 56 | LET vL.QDF.CalendarGenMinDate = Num(Date(Date#(Date(Peek('QDF.CalendarGenMinDate',0,'QDF.CalendarGenMinMax')), '$(vL.QDF.DateFormat)'))); 57 | LET vL.QDF.CalendarGenMaxDate = Num(Date(Date#(Date(Peek('QDF.CalendarGenMaxDate',-1,'QDF.CalendarGenMinMax')), '$(vL.QDF.DateFormat)'))); 58 | 59 | DROP TABLE CalendarGenMinMax; 60 | 61 | endif 62 | 63 | if not '$(vL.QDF.CalendarGenMinDate)'='' then // If we can't find min or max date skipp calendar 64 | 65 | LET vL.QDF.CalendarGenToday = Num(Today()); 66 | 67 | // Quarter map generation 68 | CalendargenQuarterMap: 69 | MAPPING LOAD * INLINE [ 70 | Month, Quarter 71 | 1, Q1 72 | 2, Q1 73 | 3, Q1 74 | 4, Q2 75 | 5, Q2 76 | 6, Q2 77 | 7, Q3 78 | 8, Q3 79 | 9, Q3 80 | 10, Q4 81 | 11, Q4 82 | 12, Q4 83 | ]; 84 | 85 | 86 | // Calendar Generation 87 | 88 | [$(vL.QDF.CalendarTableName)]: 89 | LOAD *, 90 | autoNumber([$(vL.QDF.DateFieldLinkName_new)],'$(vL.QDF.CalendarTableName)') AS [num$(vL.QDF.DateFieldLinkName_new)], 91 | autoNumber([$(vL.QDF.CalendarTableName) MonthYear],'$(vL.QDF.CalendarTableName)MonthYear') AS [$(vL.QDF.CalendarTableName) numMonthYear], 92 | autoNumber([$(vL.QDF.CalendarTableName) QuarterYear],'$(vL.QDF.CalendarTableName)QuarterYear') AS [$(vL.QDF.CalendarTableName) numQuarterYear], 93 | autoNumber([$(vL.QDF.CalendarTableName) WeekYear],'$(vL.QDF.CalendarTableName)WeekYear') AS [$(vL.QDF.CalendarTableName) numWeekYear]; 94 | LOAD 95 | [$(vL.QDF.DateFieldLinkName_new)], 96 | Week([$(vL.QDF.DateFieldLinkName_new)]) AS [$(vL.QDF.CalendarTableName) Week], 97 | Year([$(vL.QDF.DateFieldLinkName_new)]) AS [$(vL.QDF.CalendarTableName) Year], 98 | Month([$(vL.QDF.DateFieldLinkName_new)]) AS [$(vL.QDF.CalendarTableName) Month], 99 | 100 | Day([$(vL.QDF.DateFieldLinkName_new)]) AS [$(vL.QDF.CalendarTableName) Day], 101 | WeekDay([$(vL.QDF.DateFieldLinkName_new)]) AS [$(vL.QDF.CalendarTableName) WeekDay], 102 | applyMap('CalendargenQuarterMap', num(month([$(vL.QDF.DateFieldLinkName_new)])),null()) AS [$(vL.QDF.CalendarTableName) Quarter], 103 | Date(monthStart([$(vL.QDF.DateFieldLinkName_new)]), 'MM-YYYY') AS [$(vL.QDF.CalendarTableName) MonthYear], 104 | dual(applyMap('CalendargenQuarterMap', num(month([$(vL.QDF.DateFieldLinkName_new)])),null()) 105 | & '-' & Year([$(vL.QDF.DateFieldLinkName_new)]),QuarterStart([$(vL.QDF.DateFieldLinkName_new)])) AS [$(vL.QDF.CalendarTableName) QuarterYear], 106 | dual(Week([$(vL.QDF.DateFieldLinkName_new)]) & '-' & WeekYear([$(vL.QDF.DateFieldLinkName_new)]),WeekStart([$(vL.QDF.DateFieldLinkName_new)])) AS [$(vL.QDF.CalendarTableName) WeekYear], 107 | if(Year2Date([$(vL.QDF.DateFieldLinkName_new)], 0, 1, $(vL.QDF.CalendarGenToday)),1) AS [$(vL.QDF.CalendarTableName) YTD Flag], 108 | if(Year2Date([$(vL.QDF.DateFieldLinkName_new)], -1, 1, $(vL.QDF.CalendarGenToday)),1) AS [$(vL.QDF.CalendarTableName) PYTD Flag], 109 | // If(DayNumberOfQuarter($(vL.QDF.DateFieldLinkName_new)) <= DayNumberOfQuarter($(vL.QDF.CalendarGenToday)), 1, 0) as [$(vL.QDF.CalendarTableName) QTD Flag], 110 | // If(Day([$(vL.QDF.DateFieldLinkName_new)]) <= Day(Today()), 1, 0) as [$(vL.QDF.CalendarTableName) MTD Flag], 111 | If(Month([$(vL.QDF.DateFieldLinkName_new)]) = Month($(vL.QDF.CalendarGenToday)), 1, 0) as [$(vL.QDF.CalendarTableName) CurrentMonth Flag], 112 | If(Month(AddMonths([$(vL.QDF.DateFieldLinkName_new)],1)) = Month($(vL.QDF.CalendarGenToday)), 1, 0) as [$(vL.QDF.CalendarTableName) LastMonth Flag]; 113 | LOAD 114 | Date($(vL.QDF.CalendarGenMinDate) + RecNo() - 1) AS [$(vL.QDF.DateFieldLinkName_new)] 115 | AUTOGENERATE ($(vL.QDF.CalendarGenMaxDate) - $(vL.QDF.CalendarGenMinDate)+1); 116 | 117 | 118 | if not '$(vL.QDF.MonthsLeftFiscalDates)' = '' then 119 | /*Catch scenario where negative number of months provided rather than remaining months 120 | If a negative value is provided it is possible to move the Fiscal Year to the 121 | Prefix rather than Suffix Year */ 122 | if $(vL.QDF.MonthsLeftFiscalDates) < 0 then 123 | vL.QDF.FiscalStartMonth = 13 - (vL.QDF.MonthsLeftFiscalDates + 12); 124 | else 125 | vL.QDF.FiscalStartMonth = 13 - vL.QDF.MonthsLeftFiscalDates; 126 | endif; 127 | 128 | 129 | Left Join ([$(vL.QDF.CalendarTableName)]) 130 | Load [$(vL.QDF.DateFieldLinkName_new)], 131 | // Fiscal Dates 132 | Year(AddMonths([$(vL.QDF.DateFieldLinkName_new)],$(vL.QDF.MonthsLeftFiscalDates))) AS [$(vL.QDF.CalendarTableName) Fiscal Year], 133 | Dual(Month([$(vL.QDF.DateFieldLinkName_new)]), Num(Month(AddMonths([$(vL.QDF.DateFieldLinkName_new)],$(vL.QDF.MonthsLeftFiscalDates))))) AS [$(vL.QDF.CalendarTableName) Fiscal Month], 134 | 'Q' & Ceil(Num(Month(AddMonths([$(vL.QDF.DateFieldLinkName_new)],$(vL.QDF.MonthsLeftFiscalDates)))) / 3) AS [$(vL.QDF.CalendarTableName) Fiscal Quarter], 135 | Date(MonthStart(AddMonths([$(vL.QDF.DateFieldLinkName_new)],$(vL.QDF.MonthsLeftFiscalDates))),'MM-YYYY') AS [$(vL.QDF.CalendarTableName) Fiscal MonthYear], 136 | dual('Q' & Ceil(Num(Month(AddMonths([$(vL.QDF.DateFieldLinkName_new)],$(vL.QDF.MonthsLeftFiscalDates)))) / 3) & '-' & Year(AddMonths([$(vL.QDF.DateFieldLinkName_new)],$(vL.QDF.MonthsLeftFiscalDates))), 137 | QuarterStart(AddMonths([$(vL.QDF.DateFieldLinkName_new)],$(vL.QDF.MonthsLeftFiscalDates)))) AS [$(vL.QDF.CalendarTableName) Fiscal QuarterYear], 138 | if(YearToDate([$(vL.QDF.DateFieldLinkName_new)], 0, $(vL.QDF.FiscalStartMonth), $(vL.QDF.CalendarGenToday)),1,0) AS [$(vL.QDF.CalendarTableName) Fiscal YTD Flag], 139 | if(YearToDate([$(vL.QDF.DateFieldLinkName_new)], -1, $(vL.QDF.FiscalStartMonth), $(vL.QDF.CalendarGenToday)),1,0) AS [$(vL.QDF.CalendarTableName) Fiscal PYTD Flag] 140 | // End Fiscal Dates 141 | Resident [$(vL.QDF.CalendarTableName)]; 142 | 143 | endif 144 | //drop field tmp_Calendar; 145 | 146 | if vL.QDF.IndexFields_tmp = 0 then 147 | let vL.QDF.DateFieldLinkName_Derive='[$(vL.QDF.DateFieldLinkName_new)]'; 148 | else 149 | let vL.QDF.DateFieldLinkName_Derive='$(vL.QDF.DateFieldLinkName_Derive)'&', [$(vL.QDF.DateFieldLinkName_new)]'; 150 | endif 151 | 152 | else 153 | trace '### DF Error Did not find min and max dates, Is this a date field?, ending CalendarGen'; 154 | endif 155 | 156 | // Cleanup 157 | 158 | SET vL.QDF.DateFieldLinkName_new=; 159 | Set vL.QDF.CalendarGenMinDate = ; 160 | Set vL.QDF.CalendarGenMaxDate = ; 161 | 162 | // Add basic Qlik Sense calendar in UI (if Sense is identifyed) 163 | if lower(left('$(vG.BasePath)',3))='lib' and not '$(vL.QDF.DateFieldLinkName_Derive)' = '' then 164 | [std]: // will create a virtual calendar named $(vL.QDF.CalendarTableName).cal 165 | DECLARE FIELD DEFINITION Tagged ('$date') // Sort order 166 | FIELDS 167 | Dual(Year($1), YearStart($1)) AS [Year] Tagged ('$axis', '$year'), 168 | Dual('Q'&Num(Ceil(Num(Month($1))/3)),Num(Ceil(NUM(Month($1))/3),00)) AS [Quarter] Tagged ('$axis', '$quarter'), 169 | Dual(Year($1)&'-Q'&Num(Ceil(Num(Month($1))/3)),QuarterStart($1)) AS [YearQuarter] Tagged ('$axis', '$yearquarter'), 170 | Month($1) AS [Month] Tagged ('$month'), 171 | Dual(Year($1)&'-'&Month($1), monthstart($1)) AS [YearMonth] Tagged ('$axis', '$yearmonth'), 172 | Dual(W&Num(Week($1),00), Num(Week($1),00)) AS [Week] Tagged ('$axis', '$weeknumber'), 173 | Day($1) as Day Tagged ('$axis', '$day'), 174 | Date(floor($1)) as Date Tagged ('$axis', '$date'); 175 | 176 | 177 | Derive Fields from Fields $(vL.QDF.DateFieldLinkName_Derive) Using [std]; 178 | endif 179 | 180 | Next vL.QDF.IndexFields_tmp 181 | 182 | Set vL.QDF.FindFieldTableName = ; 183 | Set vL.QDF.DateFieldLinkName = ; 184 | Set vL.QDF.CalendarTableName = ; 185 | Set vL.QDF.CalendarGenMinDateOrg = ; 186 | Set vL.QDF.CalendarGenMaxDateOrg = ; 187 | SET vL.QDF.CalendarGenToday = ; 188 | SET vL.QDF.MonthsLeftFiscalDates = ; 189 | SET vL.QDF.FiscalStartMonth = ; 190 | SET vL.QDF.DateFormat=; 191 | SET vL.QDF.DateFormat_old=; 192 | SET vL.QDF.DateFormatOrg=; 193 | SET vL.QDF.DateFieldLinkName_Derive=; 194 | 195 | 196 | END SUB 197 | -------------------------------------------------------------------------------- /3.Include/1.BaseVariable/1.Init.qvs: -------------------------------------------------------------------------------- 1 | // __________________________________________________________ 2 | // Qlik Deployment Framework BaseVariable 1.Init.qvs 3 | // This Include populates global variables 4 | // All global path are based on vG.BasePath that is identified first 5 | // ___________________________________________________________ 6 | 7 | trace '### QDF Info, Initiation Started'; // Writing information in QlikView application log 8 | 9 | // To link Shared_Folders directly into 1.init.qvs set vL.QDF.LinkShared_Folders = 'Shared' (link name) 10 | // Leave vL.QDF.LinkShared_Folders blank to skip linking to shared folders 11 | SET vL.QDF.LinkShared_Folders = 'Shared'; 12 | 13 | // To create Custom Global Variables from current container (vG.BaseVariablePath) 14 | // set vL.QDF.LoadvL.QDF.BasePath=CustomVG to variable csv file name, default 'Custom*.csv' 15 | // Remark or blank vL.QDF.LoadCustomVG to skip loading Custom Global Variables 16 | set vL.QDF.LoadCustomVG='Custom*.csv'; 17 | 18 | // To create Universal Variables from Shared Files container (vG.SharedBaseVariablePath) 19 | // set vL.QDF.LoadCustomVU to variable csv file name, default 'Custom*.csv' 20 | // Remark or blank vL.QDF.LoadCustomVU to skip loading Universal Variables 21 | set vL.QDF.LoadCustomVU='Custom*.csv'; 22 | 23 | // Sub function vL.GetContainerStructure containing possible container folders (vL.ContainerStructure table) 24 | sub GetContainerStructure; 25 | vL.ContainerStructure: 26 | REPLACE LOAD * INLINE [ 27 | PhysicalFolderName, VariablePrefix, Subfolder, Comments 28 | Application, Application, , QlikView Applications are resided in subfolders under 1.Applications 29 | QVD, QVD, , QlikView Data files are stored in subfolders under 2.QVD 30 | Include, Include, , Folder where QlikView Include files are stored. These are script parts that are called from the main QlikView script. 31 | Mart, Mart, , "Resides QlikView Qvw marts (in subfolders) for data discovery usage, these folders could be shared." 32 | Config, Config, , Configuration and language files like Excel and txt. This folders could be shared to make configuration changes easier 33 | Script, Script, , Store for special scripts run by the publisher or scheduled tasks 34 | Export, Export, , "Folder used to store from QlikView exported data, probably txt or qvx" 35 | Import, Import, , Folder used to store import data from external systems 36 | BaseVariable, BaseVariable, Include, "Stores all the variables needed to use the framework, like paths inside the container" 37 | Locale, Locale, Include, "Locale for different regions, used for easy migration between regions" 38 | ConnString, ConnString, Include, Stores connection strings to data sources 39 | Sub, Sub, Include, "Store for sub routines, this is a way to reuse code between applications" 40 | ColorScheme, ColorScheme, Include, Company standard Color Scheme would be placed here 41 | Custom, Custom, Include, Store for custom include scripts 42 | Template, Template, , Used to identify Admin container and create extra variables used by Variable Editor 43 | Extract, Extract, QVD, Optional store for data extracts 44 | Transform, Transform, QVD, Optional store for data transformation 45 | Load, Load, QVD, Optional store for data load 46 | ]; 47 | end sub; 48 | 49 | // Cleanup, Removing old Path Value 50 | SET vG.TemplatePath =; 51 | 52 | 53 | if '$(vL.QDF.BaseVariablePath)' = '' then // if initiation done via Initlink skip this step 54 | LET vL.QDF.RootPath_tmp='$(vG.RootPath)'; // vL.QDF.RootPath_tmp is used to identify global variable cache 55 | LET vL.QDF.BasePath_tmp='$(vG.BasePath)'; // vL.QDF.BasePath_tmp is used to identify global variable cache 56 | 57 | SET vG.BasePath=; 58 | SET vG.RootPath=; 59 | 60 | //***************** Initiation for Qlik Sense and QlikView ********************************** 61 | // Qlik Sense additions Validating if LIB root exists if yes then add this as vG.RootPath 62 | // Validate Separate LIB mounts 63 | if not '$(vG.HomeContainer)' = '' and not IsNull(filesize('lib://$(vG.HomeContainer)/Initlink.qvs')) = -1 then 64 | LET vG.BasePath= 'lib://$(vG.HomeContainer)/'; 65 | trace '### DF Info, identified Sense home container $(vG.BasePath) (Separate LIB mounts)'; 66 | elseif not '$(vG.HomeContainer)' = '' and not IsNull(filesize('$(vG.HomeContainer)/Initlink.qvs')) = -1 then 67 | LET vG.BasePath= '$(vG.HomeContainer)/'; 68 | trace '### DF Info, identified Sense home container $(vG.BasePath) (Separate LIB mounts)'; 69 | elseif '$(vG.HomeContainer)' = '' and not IsNull(filesize('lib://Shared/*')) = -1 then 70 | LET vG.BasePath= 'lib://Shared/'; 71 | trace '### DF Info, identified Sense Shared home container (Separate LIB mounts)'; 72 | elseif '$(vG.HomeContainer)' = '' and not IsNull(filesize('lib://shared/*')) = -1 then 73 | LET vG.BasePath= 'lib://shared/'; 74 | trace '### DF Info, identified Sense shared home container (Separate LIB mounts)'; 75 | else // Validate single LIB mount 76 | if not '$(vG.RootContainer)' = '' and not IsNull(filesize('lib://$(vG.RootContainer)/*')) = -1 then 77 | LET vG.RootPath= 'lib://$(vG.RootContainer)/'; 78 | trace '### DF Info, identified Sense root path $(vG.RootPath) (single LIB mount)'; 79 | SET vG.RootContainer = ; 80 | elseif not '$(vG.RootContainer)' = '' then 81 | trace '### DF Warning, could not find root container with name $(vG.RootContainer)'; 82 | SET vG.RootContainer = ; 83 | elseif not IsNull(filesize('lib://Root/*')) = -1 then 84 | LET vG.RootPath= 'lib://Root/'; 85 | trace '### DF Info, identified Sense root path $(vG.RootPath) (single LIB mount)'; 86 | elseif not IsNull(filesize('lib://root/*')) = -1 then 87 | LET vG.RootPath= 'lib://root/'; 88 | trace '### DF Info, identified Sense root path $(vG.RootPath) (single LIB mount)'; 89 | endif 90 | 91 | // Validate fixed root url 92 | if not '$(vG.HomeContainer)'='' and not IsNull(filesize('$(vG.RootPath)$(vG.HomeContainer)\Initlink.qvs')) = -1 then 93 | LET vG.BasePath= '$(vG.RootPath)$(vG.HomeContainer)\'; 94 | trace '### DF Info, identified Sense home container $(vG.BasePath)'; 95 | elseif not '$(vG.RootPath)' = '' and not IsNull(filesize('$(vG.RootPath)99.Shared_Folders/*')) = -1 then 96 | LET vG.BasePath= '$(vG.RootPath)99.Shared_Folders/'; 97 | trace '### DF Info, identified Sense home container $(vG.BasePath)'; 98 | elseif not '$(vG.RootPath)' ='' then // Search for Initlink.qvs in a valid container under Root 99 | for each vL.QDF.DoDir in dirlist ('$(vG.RootPath)*') 100 | if filesize('$(vL.QDF.DoDir)\Initlink.qvs') > 1 then 101 | LET vG.BasePath= '$(vL.QDF.DoDir)\'; 102 | trace '### DF Info, identified Sense home container $(vG.BasePath)'; 103 | endif 104 | exit for when not '$(vG.BasePath)'=''; 105 | next vL.QDF.DoDir 106 | set vL.QDF.DoDir=; 107 | else // This is the QlikView vG.BasePath initiation section 108 | LET vG.BasePath=; 109 | for vL.x_loop =1 to 20-1 110 | LET vL.QDF.InitLinkPath_tmp='$(vL.QDF.InitLinkPath)'; 111 | if FileTime('$(vL.QDF.InitLinkPath)InitLink.qvs') > 0 then 112 | // Set vG.BasePath based on InitLink.qvs location 113 | LET vG.BasePath=left(DocumentPath(),index(DocumentPath(),'\', -(substringcount( '$(vL.QDF.InitLinkPath)','\' )+1))); 114 | endif 115 | LET vL.QDF.InitLinkPath='..\'&'$(vL.QDF.InitLinkPath_tmp)'; 116 | exit for when not '$(vG.BasePath)'= '' 117 | next 118 | SET vL.QDF.InitLinkPath = ; 119 | SET vL.QDF.InitLinkPath_tmp = ; 120 | SET vL.x_loop = ; 121 | endif 122 | endif 123 | 124 | SET vG.HomeContainer = ; 125 | SET vG.RootContainer = ; 126 | //***************** Initiation for Qlik Sense and QlikView done ********************************** 127 | endif 128 | 129 | // Check if vG.BasePath variable exists, else exit the script 130 | 131 | If '$(vG.BasePath)'= '' then 132 | trace '### DF Warning, could not identify any valid container path, will exit'; 133 | trace '### DF Warning, if using Qlik Sense add SET vG.HomeContainer=container name before InitLink.qvs'; 134 | LET vG.BasePath=; 135 | exit script; 136 | elseif not '$(vL.QDF.BasePath_tmp)'='$(vG.BasePath)' then //Validate if BasePath is same as last itteration, if true will use cache 137 | 138 | // Open vL.ContainerStructure include table 139 | Call GetContainerStructure ; 140 | 141 | // Loop to create Container Global Variable Path 142 | FOR vL.QDF.VariableLoop = 0 to NoOfRows('vL.ContainerStructure')-1; 143 | let vL.QDF.PhysicalFolderName = Peek(FieldName(1,'vL.ContainerStructure'),$(vL.QDF.VariableLoop), vL.ContainerStructure); 144 | let vL.QDF.VariablePrefix = Peek(FieldName(2,'vL.ContainerStructure'),$(vL.QDF.VariableLoop), vL.ContainerStructure); 145 | let vL.QDF.Subfolder = Peek(FieldName(3,'vL.ContainerStructure'),$(vL.QDF.VariableLoop), vL.ContainerStructure); 146 | 147 | if not '$(vL.QDF.Subfolder)'='' then 148 | if not '$(vL.QDF.Subfolder)'=Peek(FieldName(3,'vL.ContainerStructure'),$(vL.QDF.VariableLoop)-1, vL.ContainerStructure) then 149 | 150 | for each vL.QDF.DoDir in dirlist ('$(vG.BasePath)*') 151 | if right('$(vL.QDF.DoDir)',len('$(vL.QDF.Subfolder)'))='$(vL.QDF.Subfolder)' then 152 | LET vL.QDF.BasePath='$(vL.QDF.DoDir)\'; 153 | endif 154 | next vL.QDF.DoDir 155 | endif 156 | else 157 | LET vL.QDF.BasePath='$(vG.BasePath)'; 158 | endif 159 | for each vL.QDF.DoDir in dirlist ('$(vL.QDF.BasePath)*') //Search for a valid container under Root 160 | if right('$(vL.QDF.DoDir)',len('$(vL.QDF.PhysicalFolderName)'))='$(vL.QDF.PhysicalFolderName)' then 161 | SET vG.$(vL.QDF.VariablePrefix)Path='$(vL.QDF.DoDir)\'; 162 | endif 163 | exit for when right('$(vL.QDF.DoDir)',len('$(vL.QDF.PhysicalFolderName)'))='$(vL.QDF.PhysicalFolderName)' 164 | 165 | next vL.QDF.DoDir 166 | Next vL.QDF.VariableLoop 167 | SET vL.QDF.DoDir=; 168 | 169 | // Dropping vL.ContainerStructure table when the Base Global Variables are read into QlikView 170 | drop table vL.ContainerStructure ; 171 | 172 | // Special check, Qlik Sense is using LIB's and do not need a root folder 173 | if '$(vG.RootPath)'='' and not lower(left(trim('$(vG.BasePath)'),6))='lib://' then 174 | $(Include=$(vG.SubPath)\3.LoadContainerMap.qvs); 175 | // Identifying where RootPath is in the container structure 176 | call LoadContainerMap('$(vG.BaseVariablePath)\ContainerMap.csv','','$(vG.BasePath)'); 177 | endif 178 | 179 | //Remove vG.SharedBasePath variable, this will clear shared cache 180 | set vG.$(vL.QDF.LinkShared_Folders)BasePath=; 181 | 182 | else 183 | trace '### QDF Info, Global Variables using cache'; 184 | LET vG.RootPath='$(vL.QDF.RootPath_tmp)'; // Set RootPath to cached value 185 | endif 186 | 187 | 188 | // Shared_Folders Initiation 189 | if not IsNull(filesize('$(vG.$(vL.QDF.LinkShared_Folders)BasePath)\Initlink.qvs'))=-1 then 190 | trace '### QDF Info, $(vL.QDF.LinkShared_Folders) Global Variables using cache'; 191 | else 192 | $(Include=$(vG.SubPath)\4.GenericContainerLoader.qvs); 193 | // Load Include for LCGV function 194 | // This function is to be used inside the Qlik scripts to link between containers 195 | CALL LCGV('$(vL.QDF.LinkShared_Folders)'); 196 | 197 | if IsNull(filesize('$(vG.$(vL.QDF.LinkShared_Folders)BasePath)\Initlink.qvs'))=-1 then 198 | set vL.QDF.LinkShared_Folders =; // If no shared container found remove link 199 | trace '### QDF Info, Shared container is missing'; 200 | endif 201 | endif; 202 | 203 | // 99.LoadAll.qvs pre-loads QDF function-library, for easy access 204 | $(Include=$(vG.$(vL.QDF.LinkShared_Folders)SubPath)\99.LoadAll.qvs); 205 | 206 | // Loading Universal Variables (CustomVariable file) from Shared Container 207 | call LoadVariableCSV('$(vG.$(vL.QDF.LinkShared_Folders)BaseVariablePath)\$(vL.QDF.LoadCustomVU)'); 208 | 209 | // Loading from Base Container CustomVariable file 210 | call LoadVariableCSV('$(vG.BaseVariablePath)\$(vL.QDF.LoadCustomVG)'); 211 | 212 | // Initiation of 4.Custom from Shared or (home container if Shared is missing) 213 | $(Include=$(vG.$(vL.QDF.LinkShared_Folders)BaseVariablePath)\4.Custom.qvs); 214 | 215 | // Initiation of 4.Custom within home container 216 | $(Include=$(vG.BaseVariablePath)\4.Custom.qvs); // Loading 4.Custom from current container 217 | 218 | // Clean up 219 | // Remove local variables 220 | SET vG.QVCDisable=; 221 | SET vL.QDF.PhysicalFolderName=; 222 | SET vL.QDF.VariablePrefix=; 223 | SET vL.QDF.VariableLoop=; 224 | SET vL.FileExist=; 225 | SET vL.QDF.LinkShared_Folders=; 226 | SET vL.QDF.BaseVariablePath=; 227 | set vL.QDF.LoadCustomVG=; 228 | set vL.QDF.LoadCustomVU=; 229 | set vL.RelativePath=; 230 | set vL.ContainerName=; 231 | set vL.Root=; 232 | SET vL.QDF.IncludeFolder=; 233 | SET vL.QDF.BaseVariableFolder=; 234 | SET vL.QDF.Subfolder=; 235 | SET vL.QDF.BasePath=; 236 | SET vL.QDF.BasePath_tmp=; 237 | SET vL.QDF.RootPath_tmp=; 238 | SET vL.QDF.SharedPath_tmp=; 239 | 240 | // Writing information in log 241 | trace '### QDF Info, 1.Init.qvs Finished'; 242 | 243 | // ********************************** 244 | // 1.Init.qvs written by Magnus Berg 245 | // QlikTech International AB 246 | // ********************************** -------------------------------------------------------------------------------- /Version1.7.5.txt: -------------------------------------------------------------------------------- 1 | Whats new in release 1.7.5? 2 | New InitLinkSkip.qvs, bypass 1.init initiation steps to improve debug experiance 3 | Fixed a bug with how qvc was installed in the containers 4 | 6.CreateFolder.qvs Handle special characters in folder name for CMD pipeline /from @walteryiphk 5 | 12.Index.qvs Make sure to load correct index folder /from @walteryiphk 6 | 7 | 8 | Whats new in release 1.7.4? 9 | New function ETLLogEntry and WriteETLLog that creates an ETL log as a table and writes this log to disk when needed (15.ETLLogEntry.qvs) /thx Rod Stewart 10 | Added MIT license in containers 11 | Updated Variable Editor to work in later releases, but Variable Editor Application might not work on QlikView 12.3 and newer due to macro execution issues. Recommendation is to use Deploy Tool instead for Variable Editor 12 | 13 | Whats new in release 1.7.3? 14 | Corrections for Qlik Sense November 2018 15 | 16 | Whats new in release 1.7.2? 17 | Minor bug fixes in 5.DoDir.qvs /thx walteryiphk 18 | Fixing stability issues in 12.Index.qvs 19 | Added 13.NceTrace.qvs function to prettify output of text to the reload window /thx Göran Sander 20 | Added 14.QVDReduce.qvs function that provides the ability to reduce the size of temporary QVD files /thx Damian Waldron Qlik 21 | Loading in sub-functions earlier within 1.Init.qvs 22 | Minor cleanup in custom.qvs and LoadVariableCSV.qvs 23 | 24 | Whats new in release 1.7.1? 25 | Fixed Shared Global Variable cache behavior, vG.BasePath is now controlling cache validation alone 26 | Updated Deploy Tool making it easier to jumb between multiple QDF environments 27 | Updated Deploy Tool sorting Container Map 28 | Updated Deploy Tool removes blanks in Container Map 29 | Updated Deploy Tool it�s now possible to stretch out deploy tool. 30 | Minor IndexDel fix 31 | Minor change that removes QVC dependencies (when dissabled) in a better way 32 | Minor fixes to compencate for engine error (CFXFileSize::EvalDual) 33 | During Qlik Sense initiation Search for shared_folders and use as home container 34 | 35 | Whats new in release 1.7.0? 36 | Installer improvements, select between three container layouts: Classic, Sense and Slimmed Down 37 | New container layout, Qlik Sense Only, including extract transform load folders 38 | New container layout, slimmed down containers, including extract, transform load folders 39 | Added documentation extracts change depending on selected container layout 40 | Added code to GitHub 41 | Added Negative Fiscal Year in CalendarGen.qvs 42 | Added support for QlikView Components into 99.LoadAll.qvs 43 | Added Alias switch in LCGV, uses the added alias name instead of prefix in the generated global variables 44 | Changed Sub Function library loaded from shared folders if exist 45 | Minor updates due to Qlik Sense file format changes (returned / instead of \) 46 | Added Global Variable cache during initiation, to speed up init 47 | Added support for Qlik Sense in CreateFolder() function 48 | Enhanced scramble of num in QVDMigration function 49 | 50 | Whats new in release 1.6.0? 51 | New installer that can add additional containers in an active container structure (good for Qlik Sense) 52 | New installer that does not need QlikView during upgrade 53 | General improvements, CalendarGen.qvs Qlik Sense auto calendar 54 | 55 | Whats new in release 1.5.2? 56 | Added Qlik Sense initiation without need of a shared container 57 | Changed IndexAdd behavior, files are created directly under Index, no sub folders created anymore 58 | Changed IndexDel behavior, delete index and qvd based on the new index structure 59 | Added QVDMigration.qvs and QVDLoad.qvs optional row limitation setting 60 | Added QVDMigration.qvs transfer tags from source qvd files + add suffix as tag 61 | Added support for multiple date fields and formats in the CalendarGen function 62 | Added Native Qlik Sense Calendar support (simple version) 63 | DoDir, Qlik Sense improvements 64 | Overall Qlik Sense enhancements 65 | Documentation improvements 66 | 67 | Whats new in release 1.5.1? 68 | Added support for QlikView 12 69 | Added Major improvements of the IndexLoad function 70 | Added Smart idetification of container folders, folder numbers (1.) can be removed 71 | Added Smart idetification makes it possible to add Extract/Transfor/Load folders under the QVD folder 72 | Added Northwind (qvw,qvf) IndexLoad and LoadVariableCSV Examples in example container 73 | Added KPI.Variables.csv variable file in example container (used by Northwind) 74 | 75 | Whats new in release 1.5.0? 76 | Added the index functions IndexAdd, IndexLoad and IndexDel 77 | Added index functions into the Development Guide 78 | Changed code in how to identify a container in LoadContainerMap function (3.LoadContainerMap.qvs) 79 | Added support for tags (table comments) in the QVFileInfo function 80 | Fixed bug, DoDir function did not return initial folder when using folders only mode (5.DoDir.qvs) 81 | Stability enhancements to VariableEditor 82 | Qlik Sense enhancements to LoadContainerMap function 83 | DoDir enhancements, wild cards *sales*, *sales*.qvd now supported 84 | Added functionality in InitLink.qvs for both Sense and QlikView 85 | Added Fiscal YTD Flag and Fiscal PYTD Flag to CalendarGen function /thx qliknerd (Qlik community) 86 | Fixed minor bug in CalendarGen /thx Bo 87 | Update Info.txt files in all container folders 88 | Added validation of qvd version (Qlik Sense and QlikView) in 8.QVFileInfo.qvs 89 | Changed Index behaviour, problems found when not using table names in the Index 90 | Faster Min and Max search in CalendarGen function /thx Damian 91 | Fixed minor bug in 2.LoadVariableCSV.qvs function /thx Damian 92 | Fixed bug in IndexDel function 93 | Added support for Qualified fields in Index function 94 | Added automatic ContainerMap fail-over to shared if container is missing when trying to connect (LCGV) 95 | Fixed Qlik Sense error when Shared container is missing 96 | Fixed IndexLoad script halts when Shared container is missing 97 | Changed CalendarGen Fiscal Month field format /thx Ian Tsang 98 | Added IndexMonitor app for Qlik Sense in 0.Administration container 99 | Fixed DoDir compatibility issue in 3.SystemVariables.qvs /thx Ian Tsang 100 | 101 | Whats new in release 1.4.1? 102 | Fixed bug, CalendarGen.qvs script fails when joining fiscal years, when field have spaces./thanks Frank Billes 103 | Incremental load support for DoDir.qvs /thanks Kevin Pickering 104 | Fixed bug, LoadVariableCSV values sometimes missed 105 | Fixed bug, DCGV did not identify folders 106 | Fixed bug, wrong variable files presented after changing containers in Variable Editor 107 | Added support for Qlik Sense in 1.Init.qvs 108 | Added support for Qlik Sense in 4.GenericContainerLoader.qvs 109 | Added QlikView Deployment Framework-Qlik Sense additional notes.pdf documentation 110 | 111 | Whats new in release 1.4.0? 112 | Created a much more competent LoadVariableCSV sub function 113 | All Variables files now have a dot in between, Example Custom.Variables.csv (only new QDF set-up) 114 | Cleaned up Variable Editor settings page and divided it into two different versions 115 | Repaired Variable Editor for the use of Variable Templates we will create a KPI library 116 | Fixed bug in FileExist SUB function 117 | Simplified and added some tweaks in the Variable Editor UI 118 | Added separate Upgrade page in Variable Editor 119 | Optional Example Container including examples is now available, all examples stored in 0.Administration container are removed 120 | Fixed bug in DoDir sub function when using folder only mode 121 | Added new DoDirFileNameCount field in DoDir table 122 | Added new function DynamicContainerGlobalVariables (DCGV) that creates Global path variables based on DoDir and ContainerMap 123 | 99.LoadAll.qvs is now pre-loaded in 4.Custom.qvs (only new QDF set-up) removes the need to add sub includes any more 124 | Added 9.Misc folder in the containers, storage for documentation, extension objects or whatever needed 125 | Added None option in Deploy Tool Advanced section, to create custom container structures without adding it into Publisher 126 | Added 12.Bra.qvs regional settings 127 | 128 | Whats new in release 1.3.2? 129 | Simplified the Variable Editor UI 130 | Added Format-Spec in QVDMigrate sub function 131 | Updated MigrateQVD example with new Format-Spec switch and removed legacy QVDExport example 132 | New Batch_run.cmd example in Variable Editor Folder 133 | Fixed AltRootPath bug to hinder use of relative path 134 | Added CurrentMonth Flag LastMonth Flag in CalendarGen sub function 135 | Fixed bug in CalendarGen sub function 136 | Fixed bug in CreateFolder sub function 137 | Added 'Single Folder' and 'Qualified fields' switches in DoDir sub function 138 | Added short name (LCGV) for LoadContainerGlobalVariables, example: call LCGV('Acme','QVD') 139 | Added 'Include Sub folders' switch to QVDMigration, this will migrate all qvd's within a directory tree 140 | Added new 10.QVDLoad.qvs sub function used when loading up a complete data model from qvd files, including sub folders. 141 | Updated Example_Northwind_Mart that now uses 10.QVDLoad.qvs sub function 142 | Changed to REPLACE LOAD in 1.Init.qvd, 3.LoadContainerMap.qvs and 2.LoadVariableCSV.qvs to work better with Incremental load 143 | 144 | 145 | Whats new in release 1.3.1? 146 | Improved robustness of FileExists sub function 147 | Improved robustness of CreateFolder sub function 148 | Improved robustness of Variable Editor 149 | Added Embeddable license to Variable Editor so it will work with personal edition 150 | Added vL.FoldersOnly switch in DoDir sub function if 'true' returns only folder names 151 | Added 99.LoadAll.qvs script that loads all subfunctions in one single go 152 | 153 | Whats new in release 1.3.0? 154 | Improved DoDir sub function and changed field names 155 | Added 8.QVFileInfo.qvs sub function that will return info regarding qvd and qvw files. 156 | Added 9.QVDMigration.qvs sub function and example app 157 | Added 7.QVD-Migration-example.qvw aplication 158 | Found Bug in LoadVariableCSV sub function (thanks Steve Perry) 159 | Updated version of the Governance Dashboard script (bug fixed and added functionality) 160 | Fixed Bug that would make Variable Editor hang during start (due to inputfields) 161 | Minor Variable Editor UI improvements (new Design Layout View) 162 | VariableEditor Shortcut in Administration container 163 | Added possibility to use development release CreateGlobalVariablesByFolderName.zip 164 | Fix bug removing = when creating global variables for example Google Map 165 | Error in variable Editor when using "Save Before Reload" setting 166 | New upgrade wizard mode in Deploy tool that upgrade framework to latest release 167 | New WizardMode variable in Editor that works together with deploy tool 168 | Locale Change reame Eng to US, added Aus and UK 169 | Change ConnStrings to Must_Include in the documentation + other minor doc additions 170 | New Variable Editor function to add and remove variable files 171 | Fix error when using wrong charters in variables (charters are removed) 172 | Better check if Variable prefix is duplecated 173 | Remove Copy SystemVariables to all containers function in Variable Editor Settings 174 | Container map is now replicated to containers by use of Store into function 175 | 176 | Whats new in release 1.2? 177 | Bug found (thanks Clemens) regarding CustomVariables.csv not updating properly 178 | Container Map Editor will not copy csv files if date and time the same (less popup boxes) 179 | Identify vG.BasePath based on InitLink.qvs located in each container base (New way identifying vG.BasePath) 180 | Batch Mode added, Modify Container Map with the Variable Editor, batch script or Publisher creates the containers in background. 181 | Minor fix in 2.LoadVariableCSV.qvs, variable prefix containing a space would halt script 182 | Minor enhancements in 2.LoadVariableCSV.qvs, changed to utf8 (miss) and no longer needed to type SET in front of variable. 183 | 184 | What's new in release 1.1? 185 | Changed Variable Editor to use a Macro when reloading, much more silent now :) 186 | New switch SET vG.SkippInit ='True' will skipp 1.Init.qvs script. 187 | 188 | Whats new in release 1 (1.0)? 189 | Replacing / with \ in Container Map Editor 190 | Fixes to allow " in expressions 191 | Added CalendarGen Function 192 | Added CalendarGen example application 193 | Changed back to UTF8 after compability issiues 194 | Added Robocopy fallback if Container creation fails (see ContainerCreation.log if it's created) 195 | load several Global Container Variables at once by use of ; as separator: 196 | call LoadContainerGlobalVariables('SAP','QVD;Include;Application'); 197 | 198 | 199 | Whats new in Pre-Release 1 (0.99)? 200 | Container Icon is now created for every container, this to differentiate containers and subfolders 201 | Force lower case when identifying and creating Global Variable Path due to behavior in QVB and DocumentPath() function showing path in upper cases. 202 | Small fixes to speed up Variable Editor 203 | Found a bug in 2.LoadVariableCSV.qvs creating an error when using ' and/or , 204 | Changed utf8 to ansi in Variable editor to use special characters 205 | German locale missing (10.ger.qvs) 206 | New first page in Variable Editor 207 | 208 | Whats new in 0.98? 209 | Bugg found in GenericContainerLoader 210 | Changes in how vG.BasePath is identifyed, removes the limitation of only two levels of containers 211 | Added function for loading a single Container Variable 212 | New version of FileExist that can be used to check folders as well as files (thanks Frederik Nünning) 213 | Found bug in 3.LoadContainerMap.qvs creating error if empty row is found in the container map 214 | Bug in 2.LoadVariableCSV.qvs, complicated expressions do not calculate properly 215 | Bug in 2.LoadVariableCSV.qvs, ContainerMapMode does not work 216 | New 6.CreateFolder.qvs Function will validate and create missing folders 217 | QV System Monitor v4.1 are Included and configured to work with DF 218 | Variable Editor Container Map will now add file emty rows in the end when needed (instead of working with 200 rows), this to increase reload speed 219 | Variable Editor editor will now add file emty rows in the end when needed (instead of working with 999 rows), this to increase reload speed 220 | 221 | Whats new in 0.97? 222 | Minor Variable Editor Bug Fixes 223 | Less command line boxes when creating containers 224 | Changed name of 5.Custom.qvs to 4.Custom.qvs 225 | Added 4.Custom.qvs in the 1.Init script 226 | Base include scripts are set to Read Only in the Template 227 | Container base scripts are set to Read Only by using Attrib +R 228 | Removed Meta Scanner that will be replaced by Governance Dashboard 229 | Changed name on System Monitor folder from 2.QlikViewSystemMonitor to 1.QlikViewSystemMonitor 230 | 231 | Whats new in 0.96? 232 | Minor changes in 2.LoadVariableCSV.qvs so that LET function removes space 233 | Better sort in Variable Editor Container Map Tree view (thanks Henrik) 234 | Changing 1.Init Containerstructure inline Table to vL.Containerstructure not to get any conflicts 235 | Variable Editor buggs 236 | 2.LoadVariableCSV.qvs, Fix so that = will work together with LET 237 | Variable Editor during start Changing to Variable tab 238 | Variable Editor fixing macro imputfield reset bug 239 | 240 | Whats new in 0.95? 241 | Added automatic upgrade functionality in Variable Editor, Put update files in 0.Template\ContainerUpgrades folder use upgrade button in Variable Editor 242 | Added new Setting in VariableEditor "Copy to Alt Root Path Containers" (Turned off by default) 243 | Added new Setting in VariableEditor "Copy Variable Editor to new Containers" 244 | Several bug fixes in VariableEditor 245 | VariableEditor cleanup 246 | New Sub function, DoDir 247 | Added hidden InitLink.qvs as default in vG.BasePath plus documenting how to Search for 1.Init.qvs in the script 248 | Added vG.TemplatePath variable if 0.Administration container is used (for Variable Editor) 249 | Added Variable to 0.template (vG.TemplatePath) in 1.init.qvs script, this variable is used by Variable Editor 250 | Version file (Version0.95.txt) now in all containers base path. Used by the upgrade function 251 | New SystemVariable Template (Pub and QVS Separated.csv) for systems with separated Publisher and QVS 252 | 253 | 254 | Whats new in 0.9? 255 | Simplifying Variable Editor when Admin 256 | Removing functionality in Variable Editor when not Admin 257 | Variable Editor cleanup 258 | Removed 4.ContainerPopulationTool 259 | 260 | Whats new in 0.86? 261 | 1.Init Scrip cleanup 262 | Easier to change or add container folderstructure in 1.Init. 263 | Only one folder configuration (1.Init) all the other scripts uses the same config. 264 | Changed trace to ### DF in the Beginning making it easier to search for DF related errors 265 | 266 | 267 | Whats new in 0.85? 268 | Minor improvments in Variable Editor, removing '-' in variable name 269 | Fixed Meta-Scanner error 270 | 271 | Whats new in 0.84? 272 | Minor improvments in Variable Editor 273 | 274 | Whats new in 0.83? 275 | Wrong path to 1.init in Meta-Scanner application 276 | 277 | 278 | Whats new in 0.82? 279 | One minor bugg 280 | 281 | Whats new in 0.81? 282 | Minor buggs 283 | 284 | Whats new in 0.8? 285 | Deployment Framework Global Variable Editor have been updated with many new fetures: 286 | Better GUI 287 | Help 288 | Are you shure, boxes 289 | Settings page 290 | Different templates 291 | 292 | 293 | 294 | Whats new in 0.7? 295 | New Tool called Deployment Framework Global Variable Editor (VariableEditor.qvw) that will replace ContainerPopulationTool.qvw. 296 | The new editor is a very powerful tool. We can now graphically create Global Variables in each container. 297 | But also Container Global Variable that will be stored in the Shared Folder. 298 | The Variable Editor also have a Container Map editor so that container creation and maintenance is even easier. 299 | Custom Variables are now populated by default, edit in Variable Editor 300 | With the New Container Map it's no longer needed to include extra qvs scripts for connection to other container use the call LoadContainerGlobalVariables function instead. 301 | 302 | New version of System Monitor (3.2) 303 | New auto populated System architecture view (Beta) 304 | 305 | New generic container loader 4.GenericContainerLoader.qvs making it easier to connect to other containers 306 | 307 | New SUB file 2.LoadVariableCSV.qvs contain procedure to load variables from a csv file 308 | call LoadVariableCSV('CSV_My Tables.csv', Optional vL.ContainerMapMode); 309 | 310 | New SUB file 3.LoadContainerMap.qvs contain procedure to load Container Map 311 | call LoadContainerMap('container map csv', Optional specific variable); 312 | By using vL.ContainerMapMode the csv will be treated as an ContainerMap.csv file 313 | And Container base Variables will be loaded based on ContainerMap.csv 314 | 315 | New SUB file 4.LoadContainerGlobalVariables.qvs contain procedure to dynamically load Global Variables connecting to other container 316 | call LoadContainerGlobalVariables('Name of Container to load', 'Optional use Container map from Shared Folder'); 317 | LoadContainerGlobalVariables are using LoadContainerMap.qvs and 4.GenericContainerLoader.qvs 318 | 319 | 320 | 321 | Whats new in 0.58? 322 | New version of System Monitor (3.1) 323 | Added and changed variables in 3.SystemVariables to fitt System Monitor 3.1 324 | 325 | Whats new in 0.57? 326 | Validation of the connected container folder path 327 | Automatically creation of connected container script in Create New Container tool, the scripts is stored in 99.Shared_Folders 328 | Shared_Folders is directly linked into 1.init.qvs as default with the switsh SET vL.LinkShared_Folders = '99.Shared_Folders'; 329 | Changed name on 2.SharedFolders.qvs to 99.Shared_Folders.qvs the linking is now automatically and the sequential number is unnecessary 330 | Changed name on 5.Company_department_code to 1.Company_department_code so the file have same name as folder it represents 331 | Bugs and reduncency fixes in Create New Container tool 332 | Documentation of all the changes 333 | 334 | Whats new in 0.56? 335 | Added default support for Windows 2003 in SystemSettings.qvs 336 | 337 | 338 | Whats new in 0.55? 339 | New Sub 1.FileExist.qvs to check if a file exists on the filesystem, 340 | Use before load statements to avoid errors during script load 341 | 342 | Create New Container populate tool: New copy SystemVariables.qvs into container function. 343 | 344 | Added 8.Import folder used to store import data from external systems 345 | 346 | 347 | Whats new in 0.54? 348 | Changed name on 2.Init.qvs to 2.SharedFiles.qvs this to easyer understand what that script does. 349 | Changed name on 3.Init.qvs to 3.SystemVariables.qvs this to easyer understand what that script does. 350 | 351 | Added Global Path variable in 3.SystemVariables.qvs to UserDocuments in AccessPoint's $(vG.UserDocumentPath1) 352 | 353 | Added different container scenarios (basic, system containers and ETL process) in core documentation 354 | 355 | 356 | Whats new in 0.53? 357 | CreateNewContainer.qvw template fix 358 | 359 | CreateNewContainer.qvw check if space not in container name 360 | 361 | Check in Init.1 if Framework is missing then Exit script. 362 | 363 | Trace in all scripts for easy debugging 364 | 365 | Now possible to have space in folder names (but not best practice) 366 | 367 | More core documentation 368 | 369 | Whats new in 0.52? 370 | 7.Export folder and global variable vG.ExportPath 371 | 372 | Export Example application created, DataExportExample.qvw 373 | 374 | Documentation regarding 7.Export folder 375 | 376 | New functions in ContainerPopulationTool.qvw 377 | 378 | Whats new in 0.51? 379 | 380 | Changed: 381 | 0.Administration\6.Script\2.CreateNewContainer\CreateNewContainer.qvw instead of CreateNewContainer.cmd 382 | Works much better than before 383 | 384 | Added: 385 | 0.Administration\6.Script\1.Create-prj\Remove-prj.cmd to remove -prj folders 386 | 387 | Added: 388 | 0.Administration\6.Script\3.CreateInitLinks\RemoveInitLinks.cmd to remove InitLinks 389 | 390 | Added: 391 | 0.Administration\3.Include\1.BaseVariable\5.Administration.qvs script to connect to 0.Administration container from another container. 392 | 393 | Added: 394 | 0.Administration\6.Script\4.ContainerPopulationTool\ContainerPopulationTool.qvw, a tool that finds vG.xx path variables from the MetaData repository 395 | and have the posibility to populate filestructure based on the variables. 396 | 397 | 398 | Added: 399 | More core documentation 400 | -------------------------------------------------------------------------------- /3.Include/4.Sub/12.Index.qvs: -------------------------------------------------------------------------------- 1 | ; 2 | //____________________________________________________________________________ 3 | // IndexAdd creates a QVD index. The index is based on meta-data and tags collected from the QVD header. The index can thereby be recreated if need be. The index default location is $(vG.SharedConfigPath)/Index location can be modified if needed. Execute IndexAdd sub function inside the script: 4 | // Call IndexAdd(‘QVD path and name’,['Index folder name'] ,['Container name'] ,['Tags'] ,['Alternative Index path']) 5 | // 6 | // • QVD path and name Path and name of QVD file to Index, wild card (*.qvd) is supported 7 | // • Index folder name (Optional) create a custom Index name, default is qvd path 8 | // • Container name (Optional) Specify the QVD files container name, this is usually identified automatically 9 | // • Tags (Optional) Add index tag, recommendation is to use the comment table function instead as this will be more persistent. 10 | // • Alternative Index path (Optional) will change the default Index path ($(vG.SharedConfigPath)/Index) This is not recommended as all functions would need the alternative path specified 11 | // Examples: 12 | // Call IndexAdd(‘vG.QVDPath\Customers.qvd’); Will add an index for Customers.qvd file 13 | // Call IndexAdd(‘vG.QVDPath\*.qvd’); Will add an index for all qvd files in vG.QVDPath path 14 | 15 | // Using Comment field to tag QVD data 16 | // It is strongly recommended to add tags into your qvd data files, these tags will identify what data to load. For example if we create an aggregated QVD data layer it could be tagged -for example- as Level2 (where level 1 is un-aggregated). This is done by adding tag (or tags) into the qvd using the Comment Table function. This should be done before storing the QVD, creating the index using IndexAdd should be done after Store, as shown in this example: 17 | // Comment Table [$(vL.TableName)] with 'Level2'; 18 | // Store [$(vL.TableName)] into '$(vG.QVDPath)\Folder\$(vL.TableName).qvd'; 19 | // Call IndexAdd('$(vG.QVDPath)\Folder\$(vL.TableName).qvd'); 20 | // Several tags can be added using comma (,) as separator as shown below: 21 | // Comment Table [$(vL.TableName)] with 'Level2,SalesAgg'; 22 | // ____________________________________________________________________________ 23 | 24 | SUB IndexAdd(vL.QDF.IndexQVD,vL.QDF.IndexFolderName,vL.QDF.ContainerPathName,vL.QDF.TAG,vL.QDF.AltIndexPath); 25 | 26 | if not right( trim('$(vL.QDF.IndexQVD)') , 4)= '.qvd' then // add .qvd if needed 27 | let vL.QDF.IndexQVD ='$(vL.QDF.IndexQVD)*.qvd'; 28 | endif 29 | 30 | Call DoDir ('$(vL.QDF.IndexQVD)', '_tmp_DoDir','','','true'); //Dir of QVD source directory 31 | 32 | let vL.QDF.DoDir = NoOfRows('_tmp_DoDir'); //No of rows in DoDir table 33 | 34 | //Validate vL.QDF.DoDir 35 | if vL.QDF.DoDir > 0 then 36 | 37 | for vL.QDF.LoopFromDoDir = 0 to vL.QDF.DoDir-1 38 | LET vL.QDF.IndexQVD = peek('_tmp_DoDir.FullyQualifiedName',$(vL.QDF.LoopFromDoDir),'_tmp_DoDir'); // Get QVD filename 39 | LET vL.QDF.QVDFileName= peek('_tmp_DoDir.DoDirFileName',$(vL.QDF.LoopFromDoDir),'_tmp_DoDir'); // Get Qvd FileName 40 | 41 | if not '$(vL.QDF.AltIndexPath)' = '' then // set alternative Index path 42 | call vL.FileExist ('$(vL.QDF.AltIndexPath)'); 43 | if '$(vL.FileExist)'='true' then 44 | Let vL.QDF.SharedConfigPath= '$(vL.QDF.AltIndexPath)'; 45 | //--- Create Index base folder ---- 46 | endif 47 | else 48 | Let vL.QDF.SharedConfigPath= '$(vG.SharedConfigPath)'; // default Index path 49 | endif 50 | 51 | //---------------------------- Collect Meta Data using QVFileInfo --------------- 52 | 53 | call QVFileInfo('$(vL.QDF.IndexQVD)','vL.__TMP_Table'); // Get Meta information regarding the QVD file and stor in vL.__TMP_Table 54 | 55 | let vL.QDF.LoopTo = NoOfRows('vL.__TMP_Table_Fields'); 56 | if vL.QDF.LoopTo > 0 then //Add metadata only if vL.__TMP_Table_Fields exist 57 | 58 | if '$(vL.QDF.TAG)' = '' then // If comment field's blank identify fields automatically 59 | 60 | Let vL.QDF.TAG=peek('QVTableComment',0,'vL.__TMP_Table'); 61 | endif 62 | Let vL.QDF.FQFN = peek('FullyQualifiedName',0,'vL.__TMP_Table'); 63 | 64 | 65 | Let vL.QDF.FileTime = num(timestamp(peek('QVFileTime',0,'vL.__TMP_Table'),'$(DateFormat)')); //Get Time and Date 66 | let vL.QDF.QVTableName = peek('QVTableName',0,'vL.__TMP_Table'); 67 | Let vL.QDF.QVTableCreator = peek('QVTableCreator',0,'vL.__TMP_Table'); // Get QVTableCreator 68 | let vL.QDF.QVNoRows = peek('QVTableNbrRows',0,'vL.__TMP_Table'); 69 | let vL.QDF.QVNofields = peek('QVTableNbrFields',0,'vL.__TMP_Table'); 70 | let vL.QDF.QVDFileName = peek('QVFileName',0,'vL.__TMP_Table'); 71 | 72 | 73 | for vL.QDF.LoopFrom = 0 to vL.QDF.LoopTo 74 | LET vL.QDF.Fields = '$(vL.QDF.Fields)'&','& peek('QVFieldName',$(vL.QDF.LoopFrom),'vL.__TMP_Table_Fields'); // concatenate fields using ; as separator 75 | LET vL.QDF.QVType = '$(vL.QDF.QVType)'&','& peek('QVType',$(vL.QDF.LoopFrom),'vL.__TMP_Table_Fields'); // concatenate fields using ; as separator 76 | if peek('QVType',$(vL.QDF.LoopFrom),'vL.__TMP_Table_Fields')='D' or peek('QVType',$(vL.QDF.LoopFrom),'vL.__TMP_Table_Fields')='R' or peek('QVType',$(vL.QDF.LoopFrom),'vL.__TMP_Table_Fields')='F' then // only add format if date type 77 | LET vL.QDF.QVFormat = '$(vL.QDF.QVFormat)'&','& peek('QVFormat',$(vL.QDF.LoopFrom),'vL.__TMP_Table_Fields'); 78 | else 79 | LET vL.QDF.QVFormat = '$(vL.QDF.QVFormat)'&','; // blank line 80 | endif 81 | Next vL.QDF.LoopFrom 82 | 83 | drop table vL.__TMP_Table ; 84 | drop table vL.__TMP_Table_Fields ; 85 | //---------------------------- Collect Meta Data done--------------- 86 | 87 | let vL.QDF.IndexQVD=left('$(vL.QDF.FQFN)',len('$(vL.QDF.FQFN)')-len('$(vL.QDF.QVDFileName)')); // Create folder path only 88 | 89 | If '$(vL.QDF.ContainerPathName)' = '' then // If ContainerName blank identify container automatially 90 | call LoadContainerMap('$(vG.BaseVariablePath)\ContainerMap.csv','','$(vL.QDF.IndexQVD)'); // Call LoadContainerMap function to get current container prefix Name (vL.ContainerPathName) 91 | endif 92 | 93 | let vL.QDF.FolderName=replace(replace('$(vL.RelativePath)','/','\'),'\','_'); //Replace backslash (\) with underscore (_) 94 | 95 | //--- Create Index folders or filenames if using Qlik Sense---- 96 | if '$(vL.QDF.IndexFolderName)' = '' then //If no customized Index folder name is used 97 | let vL.QDF.IndexFolderNameNew = '$(vL.QDF.ContainerPathName)$(vL.ContainerPathName)_$(vL.QDF.FolderName)'; 98 | 99 | elseif '$(vL.ContainerPathName)' = '' then // If both customized Index folder name and customized container is active 100 | let vL.QDF.IndexFolderNameNew = '$(vL.QDF.ContainerPathName)_$(vL.QDF.IndexFolderName)_$(vL.QDF.FolderName)'; 101 | 102 | else // If customized index folder name is used 103 | let vL.QDF.IndexFolderNameNew = '$(vL.ContainerPathName)_$(vL.QDF.IndexFolderName)_'; 104 | 105 | endif 106 | 107 | LET vL.QDF.ConfigPath = '$(vL.QDF.SharedConfigPath)Index\$(vL.QDF.IndexFolderNameNew)$(vL.QDF.QVDFileName).Index'; 108 | // Field names 109 | // QVDFileName,QVTableName,QVDSourcePath,QVDSourceContainerName,RelativePath,QVDTag,QVDIndexStorageName,QVDTimestamp,QVDFields,QVDTableCreator,QVDNbrRecords,QVDNbrFields 110 | 111 | unqualify 'QVDFileName','QVTableName','QVDSourcePath','QVDSourceContainerName','RelativePath','QVDTag','QVDIndexStorageName','QVDTimestamp','QVDFields','QVDTableCreator','QVDNbrRecords','QVDNbrFields','QVDFieldType'; 112 | [___vL.tmpTable]: 113 | LOAD * INLINE ['QVDFileName','QVTableName','QVDSourcePath','QVDSourceContainerName','RelativePath','QVDTag','QVDIndexStorageName','QVDTimestamp','QVDFields','QVDTableCreator','QVDNbrRecords','QVDNbrFields','QVDFieldType','QVDFieldFormat' 114 | '$(vL.QDF.QVDFileName)','$(vL.QDF.QVTableName)','$(vL.QDF.IndexQVD)','$(vL.ContainerPathName)','$(vL.RelativePath)',',$(vL.QDF.TAG),','$(vL.QDF.IndexFolderNameNew)','$(vL.QDF.FileTime)','$(vL.QDF.Fields)','$(vL.QDF.QVTableCreator)','$(vL.QDF.QVNoRows)','$(vL.QDF.QVNofields)','$(vL.QDF.QVType)','$(vL.QDF.QVFormat)']; 115 | 116 | store * from [___vL.tmpTable] into '$(vL.QDF.ConfigPath)' (txt,delimiter is ';' ); 117 | 118 | drop table [___vL.tmpTable]; 119 | 120 | else 121 | trace '### QDF Info, IndexAdd Cant find any data in $(vL.QDF.IndexQVD)'; 122 | endif 123 | 124 | 125 | // Cleanup inside loop 126 | set vL.QDF.QVNofields = ; 127 | set vL.QDF.IndexFolderNameNew=; 128 | set vL.QDF.QVNoRows = ; 129 | Set vL.QDF.ConfigPath = ; 130 | SET vL.QDF.TAG = ; 131 | Set vL.QDF.Fields = ; 132 | Set vL.QDF.LoopTo = ; 133 | Set vL.QDF.LoopFrom = ; 134 | set vL.QDF.QVNofields = ; 135 | set vL.QDF.QVNoRows = ; 136 | Set vL.FileExist = ; 137 | set vL.QDF.QVTableCreator = ; 138 | set vL.QDF.QVTableName = ; 139 | set vL.QDF.FileTime = ; 140 | Set vL.QDF.FolderName=; 141 | Set vL.QDF.QVDFileName=; 142 | Set vL.QDF.QVType =; 143 | Set vL.QDF.QVFormat =; 144 | Set vL.ContainerPathName = ; 145 | set vL.RelativePath=; 146 | Next vL.QDF.LoopFromDoDir 147 | 148 | drop table _tmp_DoDir ; 149 | 150 | endif 151 | 152 | // Cleanup 153 | 154 | Set vL.QDF.AltIndexPath = ; 155 | Set vL.QDF.IndexQVD = ; 156 | set vL.QDF.DoDir=; 157 | set vL.QDF.LoopFromDoDir=; 158 | set vL.QDF.ContainerName=; 159 | set vL.QDF.SharedConfigPath=; 160 | SET vL.ContainerFolderName=; 161 | SET vL.RootPath=; 162 | SET vL.Comment=; 163 | SET vL.QDF.ContainerPathName=; 164 | Set vL.QDF.IndexFolderName = ; 165 | 166 | END SUB 167 | 168 | //================================================================================================= 169 | //IndexLoad loads qvd data based on index search criteria’s like tags and field names. The qvd fieldname is the primary search criteria so it’s strongly recommended to have a qvd naming convention like day-month-year-TableName.qvd. 170 | //Execute IndexLoad sub function inside the script: 171 | // 172 | //Call IndexLoad([‘QVD file name’],['Table Name'] ,['Index Folder Name'] ,['Tags'] ,['Fields'] ,['Index Only'] ,['Load Max Rows'] ,[ ['Alternative Index path']) 173 | // 174 | //• QVD file name (Optional) Name of QVD to load, wild cards (*01-2015*) is supported 175 | //• Table Name (Optional) Load in a table, can be combined with QVD file name 176 | //• Index Folder Name (Optional) use this specific index only, can be combined with QVD file name 177 | //• Tags (Optional) load data containing a specific tag, can be combined with QVD file name 178 | //• Fields (Optional) load selected fields separated by comma (,) can be combined with QVD file name 179 | //• Index Only (Optional) will only load in the Index, true will use default table name (vL.QDF.QVDIndexTable). Type table name from default vL.QDF.QVDIndexTable. This is used when developing apps where the Index is needed. 180 | //• LoadMaxRows (Optional) will limit how many rows that can be loaded. This will only stop sequential QVD file to load a big QVD will probably load above this limit. 181 | //• Alternative Index path (Optional) will change the default Index path ($(vG.SharedConfigPath)/Index) This is not recommended as all functions would need the alternative path specified 182 | 183 | //Convert timestamp to date : Let vL.Date = timestamp(42031.554270833,'$(DateFormat)'); 184 | 185 | SUB IndexLoad(vL.QDF.IndexQVD,vL.QDF.Table,vL.QDF.IndexFolderName,vL.QDF.TAG,vL.QDF.InFields,vL.QDF.LoadIndexOnly,vL.QDF.LoadMaxRows,vL.QDF.AltIndexPath,vL.QDF.LoadExp); 186 | 187 | call vL.FileExist ('$(vL.QDF.AltIndexPath)'); 188 | if not '$(vL.QDF.AltIndexPath)' = '' and vL.FileExist = 'true' then // validate and select Index path 189 | Let vL.QDF.SharedConfigPath= '$(vL.QDF.AltIndexPath)\Index'; 190 | else 191 | Let vL.QDF.SharedConfigPath= '$(vG.SharedConfigPath)\Index'; 192 | endif 193 | 194 | If not '$(vL.QDF.IndexFolderName)' = '' then //Select specific Index to use 195 | let vL.QDF.IndexFolderName=trim('$(vL.QDF.IndexFolderName)')&'*' ; //Add a backslash to Index folder name 196 | endif 197 | 198 | let vL.QDF.QVDIndexTable='vL.QDF.QVDIndexTable'; // Name the Index Table 199 | If not '$(vL.QDF.LoadIndexOnly)'='' and not lower('$(vL.QDF.LoadIndexOnly)')='true' then // validate Index only switch also name custom index table name 200 | let vL.QDF.QVDIndexTable= '$(vL.QDF.LoadIndexOnly)'; // Rename Index table name 201 | endif 202 | 203 | 204 | If not '$(vL.QDF.IndexQVD)' = '' and substringcount( '$(vL.QDF.IndexQVD)' , '*') =0 then 205 | let vL.QDF.IndexQVD ='*'&'$(vL.QDF.IndexFolderName)$(vL.QDF.IndexQVD)'&'*.index'; 206 | else 207 | let vL.QDF.IndexQVD ='*$(vL.QDF.IndexFolderName).index'; 208 | endif 209 | 210 | //-----------------Load in Index folders --------------------------- 211 | Call DoDir ('$(vL.QDF.SharedConfigPath)\$(vL.QDF.IndexFolderName)', '_tmp_DoDir', 'true', '','true'); //Dir of Index directories 212 | //------------------------- end ------------------------------------ 213 | 214 | if NoOfFields('_tmp_DoDir') >0 then // Validate if DoDir Table Exists 215 | 216 | let vL.QDF.DoDir = NoOfRows('_tmp_DoDir'); 217 | 218 | for vL.QDF.LoopFromDoDir = 0 to vL.QDF.DoDir -1 219 | 220 | LET vL.QDF.IndexFile = peek('_tmp_DoDir.FullyQualifiedName',$(vL.QDF.LoopFromDoDir),'_tmp_DoDir'); 221 | 222 | if filesize('$(vL.QDF.IndexFile)\$(vL.QDF.IndexQVD)') >0 then 223 | 224 | unqualify QVDFileName,QVTableName,QVDSourcePath,QVDSourceContainerName,RelativePath,QVDTag,QVDFields,QVDNbrRecords; 225 | 226 | call vL.FileExist ('$(vL.QDF.SharedConfigPath)\IndexCache.qvd'); //Validate if cache exist 227 | 228 | if vL.FileExist='true' and '$(vL.QDF.LoadIndexOnly)'='' and (floor(num(date(filetime ('$(vL.QDF.SharedConfigPath)\IndexCache.qvd')))) -3) < num(today(2 )) then 229 | $(vL.QDF.QVDIndexTable): 230 | Load * 231 | From [$(vL.QDF.SharedConfigPath)\IndexCache.qvd] (qvd); //Load from index cache 232 | 233 | elseif '$(vL.QDF.LoadIndexOnly)'='' then // load less from index if loading data 234 | $(vL.QDF.QVDIndexTable): 235 | LOAD 236 | QVDFileName, 237 | QVTableName, 238 | QVDSourcePath, 239 | QVDSourceContainerName, 240 | RelativePath, 241 | QVDTag, 242 | QVDFields, 243 | QVDNbrRecords 244 | FROM 245 | [$(vL.QDF.IndexFile)\$(vL.QDF.IndexQVD)] (txt, utf8, embedded labels, delimiter is ';', msq);; 246 | 247 | else // load more if only the index should be loaded 248 | $(vL.QDF.QVDIndexTable): 249 | LOAD * 250 | FROM 251 | [$(vL.QDF.IndexFile)\$(vL.QDF.IndexQVD)] (txt, utf8, embedded labels, delimiter is ';', msq);; 252 | endif 253 | 254 | endif 255 | 256 | Next vL.QDF.LoopFromDoDir 257 | drop table [_tmp_DoDir]; 258 | 259 | 260 | //----------------------- Loop Index data ------------------------- 261 | 262 | if '$(vL.QDF.LoadIndexOnly)'='' and NoOfFields('$(vL.QDF.QVDIndexTable)') >0 then // If Index only swish used do not load 263 | 264 | lET vL.QDF.QVDNbrRecordsTotal =0; // Reset Total nbr of records 265 | if '$(vL.QDF.LoadMaxRows)'='' then // If max rows reach skip load 266 | let vL.QDF.LoadMaxRows = 0 ; 267 | endif 268 | 269 | let vL.QDF.DoDir = NoOfRows('$(vL.QDF.QVDIndexTable)'); 270 | 271 | for vL.QDF.LoopFromDoDir = 0 to vL.QDF.DoDir -1 272 | 273 | SET vL.QDF.LoadSwich='*'; // default load statement 274 | LET vL.QDF.QVDFileName = peek('QVDFileName',$(vL.QDF.LoopFromDoDir),'$(vL.QDF.QVDIndexTable)'); // retrieving Index data 275 | LET vL.QDF.QVTableName = peek('QVTableName',$(vL.QDF.LoopFromDoDir),'$(vL.QDF.QVDIndexTable)'); 276 | LET vL.QDF.QVDSourcePath = peek('QVDSourcePath',$(vL.QDF.LoopFromDoDir),'$(vL.QDF.QVDIndexTable)'); 277 | LET vL.QDF.QVDContainer = peek('QVDSourceContainerName',$(vL.QDF.LoopFromDoDir),'$(vL.QDF.QVDIndexTable)'); 278 | LET vL.QDF.QVDRelativePath = peek('RelativePath',$(vL.QDF.LoopFromDoDir),'$(vL.QDF.QVDIndexTable)'); 279 | LET vL.QDF.QVDTag = peek('QVDTag',$(vL.QDF.LoopFromDoDir),'$(vL.QDF.QVDIndexTable)'); 280 | LET vL.QDF.QVDFields = peek('QVDFields',$(vL.QDF.LoopFromDoDir),'$(vL.QDF.QVDIndexTable)'); 281 | LET vL.QDF.QVDNbrRecords = peek('QVDNbrRecords',$(vL.QDF.LoopFromDoDir),'$(vL.QDF.QVDIndexTable)'); 282 | LET vL.QDF.QVTableName_tmp='$(vL.QDF.QVTableName)'; //Create a table name temp variable, original is used when creating table 283 | 284 | // Validate table match 285 | if not trim('$(vL.QDF.Table)') = '' then 286 | SET vL.QDF.LoadSwich=; // Only load if tags are correct 287 | let vL.QDF.QVTableName=','&'$(vL.QDF.QVTableName)'&','; 288 | for vL.QDF.Table_tmp = 0 to (substringcount('$(vL.QDF.QVTableName)',',')-2) 289 | LET vL.QDF.filelist_tmp=TextBetween('$(vL.QDF.QVTableName)', ',' , ',' , $(vL.QDF.Table_tmp)+1 ); 290 | 291 | if substringcount(','&trim('$(vL.QDF.Table)'&',') , trim('$(vL.QDF.filelist_tmp)'))>0 then 292 | SET vL.QDF.LoadSwich='*'; 293 | LET vL.QDF.QVTableName='$(vL.QDF.filelist_tmp)'; //Set Tablename to identified tablename 294 | endif 295 | 296 | exit for when '$(vL.QDF.LoadSwich)' = '*' // Reset vL.Store_Select_tmp_new variable 297 | next vL.QDF.Table_tmp 298 | endif 299 | 300 | // Validate if Tag is available 301 | if not trim('$(vL.QDF.TAG)') = '' and not '$(vL.QDF.LoadSwich)'='' then 302 | SET vL.QDF.LoadSwich=; // Only load if tags are correct 303 | for vL.QDF.QVDTag_tmp = 0 to (substringcount('$(vL.QDF.QVDTag)',',')-2) 304 | LET vL.QDF.filelist_tmp=TextBetween('$(vL.QDF.QVDTag)', ',' , ',' , $(vL.QDF.QVDTag_tmp)+1 ); 305 | 306 | if substringcount(','&trim('$(vL.QDF.TAG)'&',') , ','&trim('$(vL.QDF.filelist_tmp)')&',')>0 then 307 | SET vL.QDF.LoadSwich='*'; 308 | endif 309 | 310 | exit for when '$(vL.QDF.LoadSwich)' = '*' // Reset vL.Store_Select_tmp_new variable 311 | next vL.QDF.QVDTag_tmp 312 | endif 313 | 314 | //--------------------------------Field loop------------------------------------------------------------ 315 | // Validate if any field is selected and if tags and table is valid 316 | if not trim('$(vL.QDF.InFields)') = '' and not '$(vL.QDF.LoadSwich)'='' then 317 | SET vL.QDF.LoadSwich=; 318 | // loop to select fields to be loaded 319 | LET vL.QDF.QVDFields_tmp=Replace(Replace(','&'$(vL.QDF.InFields)'&',',' ,',','),', ',',');// Adding (,) to identify fields in loop, uses (,) as field separators and remove unwanted spaces 320 | 321 | for vL.QDF.IndexFields_tmp = 0 to (substringcount('$(vL.QDF.QVDFields_tmp)',',')-2) 322 | LET vL.QDF.filelist_tmp=TextBetween('$(vL.QDF.QVDFields_tmp)', ',' , ',' , $(vL.QDF.IndexFields_tmp)+1 ); 323 | 324 | if substringcount('$(vL.QDF.QVDFields)',','&'$(vL.QDF.filelist_tmp)'&',') >0 then 325 | LET vL.QDF.LoadSwich='$(vL.QDF.LoadSwich)'&',[$(vL.QDF.filelist_tmp)]'; // Concatenated load statement 326 | endif 327 | 328 | next vL.QDF.IndexFields_tmp; 329 | 330 | // Remove (,) before the first concatenated field 331 | LET vL.QDF.LoadSwich= right('$(vL.QDF.LoadSwich)',len('$(vL.QDF.LoadSwich)')-1); 332 | 333 | elseif not trim('$(vL.QDF.InFields)') = '' then 334 | SET vL.QDF.LoadSwich=''; // If fields missing skip load 335 | let vL.QDF.Reason='Did not find any valid fields'; 336 | endif 337 | 338 | //-------------------------------------End Field loop------------------------------------------------------ 339 | 340 | if not '$(vL.QDF.LoadSwich)' = '' then // Validate if load is possible 341 | 342 | if not '$(vL.QDF.QVDContainer)'='' and IsNull(filesize('$(vG.$(vL.QDF.QVDContainer)BasePath)InitLink.qvs')) = -1 then // Validate if a container needs mounting 343 | call LCGV('$(vL.QDF.QVDContainer)','BasePath'); // Mount container if missing 344 | endif 345 | 346 | if not IsNull(filesize('$(vG.$(vL.QDF.QVDContainer)BasePath)$(vL.QDF.QVDRelativePath)*')) = -1 then // Validating path 347 | let vL.QDF.LoadPath='$(vG.$(vL.QDF.QVDContainer)BasePath)$(vL.QDF.QVDRelativePath)$(vL.QDF.QVDFileName)'; //Primary qvd load using containers and relative path 348 | elseif filesize('$(vL.QDF.QVDSourcePath)\$(vL.QDF.QVDFileName)') > 0 then 349 | let vL.QDF.LoadPath='$(vL.QDF.QVDSourcePath)\$(vL.QDF.QVDFileName)' ; // Secondary qvd load using hard coded URL 350 | else 351 | let vL.QDF.LoadPath=; // No qvd path found :( 352 | let vL.QDF.Reason='Missing QVD File $(vL.QDF.QVDContainer) $(vL.QDF.QVDRelativePath)'; 353 | endif 354 | 355 | if not '$(vL.QDF.LoadMaxRows)'=0 and $(vL.QDF.QVDNbrRecordsTotal) > $(vL.QDF.LoadMaxRows) then // If max rows reach skip load 356 | let vL.QDF.LoadPath=; 357 | let vL.QDF.Reason='Max row limit exeded'; 358 | endif 359 | 360 | if not '$(vL.QDF.LoadPath)'='' then 361 | 362 | // Loading selected data 363 | 364 | [$(vL.QDF.QVTableName)]: 365 | LOAD $(vL.QDF.LoadSwich) 366 | FROM 367 | [$(vL.QDF.LoadPath)] (qvd); 368 | 369 | let vL.QDF.QVDNbrRecordsTotal=$(vL.QDF.QVDNbrRecordsTotal)+$(vL.QDF.QVDNbrRecords); 370 | Trace '### QDF Info, loading: $(vL.QDF.QVTableName), Total amount of records: $(vL.QDF.QVDNbrRecordsTotal)'; 371 | 372 | // Run LoadVariableCSV to check if corresponding expression tags are avalible 373 | if lower('$(vL.QDF.LoadExp)')='true' and not '$(vL.QDF.TAG)' ='' then 374 | call LoadVariableCSV('','$(vL.QDF.TAG)','$(vL.QDF.QVDContainer)','true'); 375 | elseif not lower('$(vL.QDF.LoadExp)')='' then 376 | call LoadVariableCSV('','$(vL.QDF.LoadExp)','$(vL.QDF.QVDContainer)','true'); 377 | endif 378 | 379 | else 380 | Trace '### QDF Info, did not load: $(vL.QDF.QVDFileName) $(vL.QDF.Reason)'; 381 | endif 382 | 383 | 384 | 385 | endif 386 | 387 | Next vL.QDF.LoopFromDoDir 388 | 389 | drop table $(vL.QDF.QVDIndexTable); // Drop Index Table 390 | endif 391 | 392 | //endif 393 | 394 | 395 | 396 | else 397 | 398 | Trace '### QDF Warning, Could load Index table, probably no index exists'; 399 | endif 400 | 401 | // Cleanup 402 | SET vL.QDF.Reason=; 403 | SET=vL.QDF.LoadExp=; 404 | SET vL.QDF.QVDNbrRecordsTotal =; 405 | SET vL.QDF.QVDNbrRecords=; 406 | SET vL.QDF.TAG = ; 407 | SET vL.QDF.LoadSwich = ; 408 | SET vL.QDF.LoadPath = ; 409 | Set vL.QDF.IndexFolderName = ; 410 | set vL.QDF.QVNoRows = ; 411 | Set vL.FileExist = ; 412 | Set vL.QDF.IndexFields_tmp = ; 413 | LET vL.QDF.QVDFields=; 414 | SET vL.QDF.QVDFields_tmp=; 415 | set vL.QDF.LoadIndexOnly = ; 416 | Set vL.QDF.AltIndexPath = ; 417 | Set vL.QDF.IndexQVD = ; 418 | set vL.QDF.DoDir=; 419 | set vL.QDF.LoopFromDoDir=; 420 | set vL.QDF.filelist_tmp=; 421 | SET vL.QDF.SharedConfigPath=; 422 | SET vL.QDF.IndexFile=; 423 | SET vL.QDF.QVDIndexTable=; 424 | SET vL.QDF.QVTableName=; 425 | SET vL.QDF.QVTableName_tmp=; 426 | SET vL.QDF.QVDTag=; 427 | SET vL.QDF.QVDContainer=; 428 | SET vL.QDF.QVDRelativePath=; 429 | SET vL.QDF.QVDFileName=; 430 | SET vL.QDF.QVDSourcePath=; 431 | 432 | 433 | 434 | END SUB 435 | 436 | //================================================================================================= 437 | //IndexDel delete indexes and optionally associated qvd files. This could be needed keeping a consistent qvd strategy. Example, Storing 24 month of history indexes and qvd files older than 24 month should be removed else history will keep on growing infinite. IndexDel will search for the qvd fieldname (from the index) so it’s strongly recommended to have a qvd file naming convention, like TableName\day-month-year-TableName.qvd. 438 | // 439 | //Execute IndexDel sub function inside the script: 440 | //Call IndexDel(‘Index file name’,['Delete associated QVD files'] ,['Index Folder Name'] ,['Alternative Index path']) 441 | // 442 | //• Index file name Name of index to delete, wild cards (*) is supported 443 | //• Delete associated QVD files (Optional) if true qvd files associated to the indexes will also be deleted 444 | //• Index Folder Name (Optional) use this specific index only, can be combined with Index file name 445 | //• Alternative Index path (Optional) will change the default Index path ($(vG.SharedConfigPath)/Index) This is not recommended as all functions would need the alternative path specified 446 | // 447 | //Call IndexDel(‘2011-12*’); Deletes all Index files that starts with the name 2011-12 448 | // 449 | //Call IndexDel(‘2011-12*’,’true’); Will delete all index and associated qvd files that starts with the name 2011-12 450 | // 451 | 452 | SUB IndexDel(vL.QDF.IndexQVD,vL._DeleteQVD,vL.QDF.IndexFolderName,vL.QDF.AltIndexPath); 453 | 454 | call vL.FileExist ('$(vL.QDF.AltIndexPath)'); 455 | if not '$(vL.QDF.AltIndexPath)' = '' and vL.FileExist = 'true' then // validate and select Index path 456 | Let vL.QDF.SharedConfigPath= '$(vL.QDF.AltIndexPath)Index'; 457 | else 458 | Let vL.QDF.SharedConfigPath= '$(vG.SharedConfigPath)Index'; 459 | endif 460 | 461 | If '$(vL.QDF.IndexFolderName)' = '' then //Select specific Index to use 462 | let vL.QDF.IndexFolderName='*' ; //Add wildedcard as Index folder name 463 | else 464 | let vL.QDF.IndexFolderName='*$(vL.QDF.IndexFolderName)*' ; //Add wildedcard as Index folder name 465 | endif 466 | 467 | let vL.QDF.IndexQVD ='$(vL.QDF.IndexQVD).index'; // Add index prefix 468 | 469 | 470 | //-----------------Load in Index section--------------------------- 471 | Call DoDir ('$(vL.QDF.SharedConfigPath)\$(vL.QDF.IndexFolderName)$(vL.QDF.IndexQVD)', '_tmp_DoDir', '', '','true'); //Dir of vL.QDF.IndexQVD file or directory 472 | 473 | if NoOfFields('_tmp_DoDir') >0 then // Validate if DoDir Table Exists 474 | 475 | let vL.QDF.DoDir = NoOfRows('_tmp_DoDir'); 476 | 477 | for vL.QDF.LoopFromDoDir = 0 to vL.QDF.DoDir -1 478 | 479 | LET vL.QDF.IndexFile = peek('_tmp_DoDir.FullyQualifiedName',$(vL.QDF.LoopFromDoDir),'_tmp_DoDir'); 480 | 481 | unqualify QVDFileName,QVDSourcePath,QVDSourceContainerName,RelativePath,QVDIndexStorageName; 482 | 483 | vL._QVDIndex: 484 | LOAD QVDFileName, 485 | QVDSourcePath, 486 | QVDSourceContainerName, 487 | RelativePath, 488 | QVDIndexStorageName 489 | FROM 490 | [$(vL.QDF.IndexFile)] (txt, utf8, embedded labels, delimiter is ';', msq); 491 | Next vL.QDF.LoopFromDoDir 492 | 493 | drop table [_tmp_DoDir]; 494 | 495 | //------------------------------------------------ 496 | 497 | let vL.QDF.DoDir = NoOfRows('vL._QVDIndex'); 498 | 499 | for vL.QDF.LoopFromDoDir = 0 to vL.QDF.DoDir -1 // Retrieving index data 500 | LET vL.QDF.QVDFileName = peek('QVDFileName',$(vL.QDF.LoopFromDoDir),'vL._QVDIndex'); //Filename 501 | LET vL.QDF.QVDSourcePath = peek('QVDSourcePath',$(vL.QDF.LoopFromDoDir),'vL._QVDIndex'); //Hard coded qvd Source path, only used as backup 502 | LET vL.QDF.QVDContainer = peek('QVDSourceContainerName',$(vL.QDF.LoopFromDoDir),'vL._QVDIndex'); //ContainerName 503 | LET vL.QDF.QVDRelativePath = peek('RelativePath',$(vL.QDF.LoopFromDoDir),'vL._QVDIndex'); //RelativePath 504 | LET vL.QDF.QVDIndexStorageName = peek('QVDIndexStorageName',$(vL.QDF.LoopFromDoDir),'vL._QVDIndex'); //Index storage folder name 505 | 506 | 507 | if not '$(vL.QDF.QVDFileName)' ='' then // Delete only if a QVD name exists 508 | 509 | //----------------------- Delete Index -------------------------------- 510 | if FileSize('$(vL.QDF.SharedConfigPath)\$(vL.QDF.QVDIndexStorageName)$(vL.QDF.QVDFileName).Index') >0 then 511 | Trace '### QDF Info, delete Index $(vL.QDF.SharedConfigPath)\$(vL.QDF.QVDIndexStorageName)$(vL.QDF.QVDFileName).Index'; 512 | execute cmd.exe /Q /C pushd ^"$(vL.QDF.SharedConfigPath)\^" & Del ^"$(vL.QDF.QVDIndexStorageName)$(vL.QDF.QVDFileName).Index^" & popd; 513 | else 514 | Trace '### QDF Warning, Could not find $(vL.QDF.SharedConfigPath)\$(vL.QDF.QVDIndexStorageName)$(vL.QDF.QVDFileName).Index'; 515 | endif 516 | 517 | //----------------------- Delete QVD -------------------------------- 518 | call vL.FileExist ('$(vL.QDF.SharedConfigPath)\$(vL.QDF.QVDIndexStorageName)$(vL.QDF.QVDFileName).Index'); 519 | 520 | if lower('$(vL._DeleteQVD)') = 'true' and vL.FileExist= 'false' then 521 | 522 | if not '$(vL.QDF.QVDContainer)'='' and filesize('$(vG.$(vL.QDF.QVDContainer)BasePath)InitLink.qvs') =0 then // Validate if a container needs mounting 523 | call LCGV('$(vL.QDF.QVDContainer)','BasePath'); // loading container if missing 524 | endif 525 | 526 | if filesize('$(vG.$(vL.QDF.QVDContainer)BasePath)$(vL.QDF.QVDRelativePath)') > 0 then // validating path 527 | execute cmd.exe /Q /C pushd ^"$(vG.$(vL.QDF.QVDContainer)BasePath)^" & Del ^"$(vL.QDF.QVDRelativePath)^" & popd; 528 | Trace '### QDF Info, delete QVD $(vG.$(vL.QDF.QVDContainer)BasePath)\$(vL.QDF.QVDRelativePath)'; 529 | elseif filesize('$(vL.QDF.QVDSourcePath)\$(vL.QDF.QVDFileName)') > 0 then 530 | execute cmd.exe /Q /C pushd ^"$(vL.QDF.QVDSourcePath)^" & Del ^"$(vL.QDF.QVDFileName)^" & popd; 531 | Trace '### QDF Info, delete QVD $(vL.QDF.QVDSourcePath)\$(vL.QDF.QVDFileName)'; 532 | else 533 | Trace '### QDF Warning, Could not find $(vL.QDF.QVDSourcePath)\$(vL.QDF.QVDFileName)'; 534 | endif 535 | 536 | endif 537 | endif 538 | 539 | next 540 | if vL.QDF.DoDir > 0 then 541 | drop table vL._QVDIndex; 542 | endif 543 | else 544 | trace '### QDF Info, Found no index to delete'; 545 | endif 546 | 547 | 548 | 549 | // Cleanup 550 | Set vL.QDF.IndexFolderName = ; 551 | Set vL.FileExist = ; 552 | Set vL.QDF.AltIndexPath = ; 553 | Set vL.QDF.IndexQVD = ; 554 | set vL.QDF.DoDir=; 555 | set vL.QDF.LoopFromDoDir=; 556 | set vL.QDF.QVDSourcePath=; 557 | set vL.QDF.IndexFile=; 558 | set vL.QDF.QVDFileName=; 559 | set vL.QDF.QVDContainer=; 560 | set vL.QDF.QVDRelativePath=; 561 | set vL.QDF.QVDIndexStorageName=; 562 | set vL.QDF.QVDSourcePath=; 563 | 564 | END SUB 565 | 566 | // ************************************* 567 | // Functions written by Magnus Berg Qlik 568 | // ************************************* 569 | --------------------------------------------------------------------------------