Unlock a world of possibilities! Login now and discover the exclusive benefits awaiting you.
Hi all,
Background Info:
I'm working on a documentation initiative at my company. Part of that initiative is to write glossaries for our production documents that define all of the dimensions included in the documents. To do that, I needed to take an inventory of all the fields a document uses, which is simple enough using the Document Analyzer. I also needed to track how the fields were renamed in the interface. I did the first few manually by looking at every view in the documents and writing stuff down... which is a little silly, given the range of powerful tools at my disposal. I wanted to use the Document Analyzer 2.8 to link all of the Dimension Names to all of the ways that they were renamed in the interface (I called these intname in the macros, short for InterfaceName). I am primarily concerned with renamed fields in Graphs, Listboxes, Multiboxes, and Table Boxes, though other objects likely work in a similar way. I'm relatively new to Qlikview, and have no experience in VB Script or XML; please let me know if you can think of a way to improve my work, or expand upon it.
Steps:
I'm working with Document Analyzer 2.8. Here are the macros I tweaked; I've added the lines in cyan text.
Rem *** xpath expressions used to find Dimensions
Sub buildDimensionXPath
dimensionXPath = buildXPath(dimensionXPath, "//*/PseudoDef") ' Graph
dimensionXPath = buildXPath(dimensionXPath, "//*/Def") ' Listbox
dimensionXPath = buildXPath(dimensionXPath, "//*/MultiBoxMemberAttributes") 'Multi Box
dimensionXPath = buildXPath(dimensionXPath, "//*/Name1") ' Slider
dimensionXPath = buildXPath(dimensionXPath, "//*/Field") ' Table Box
End Sub
Rem *** Extract the dimensions from an XML DOM
Sub extractDimensions(id)
log "Extracting Dimensions"
Set objNodeList = xmlDoc.documentElement.selectNodes(dimensionXPath)
For Each node in objNodeList
Set child = node.selectSingleNode(".//Name")
If child Is Nothing Then name = Null Else name = child.Text
Set child = node.selectSingleNode(".//Type")
If child Is Nothing Then dtype = Null Else dtype = child.Text
Set child = node.selectSingleNode("..//Title/v")
If child Is Nothing Then Set child = node.selectSingleNode(".//Label/v")
If child Is Nothing Then intname = Null Else intname = child.Text
If Not IsNull(name) Then Call writeDimension(id, name, dtype, intname)
Next
End Sub
Rem *** Write info for a Dimension to external file
Sub writeDimension(id, name, dtype, intname)
dimensionsFile.WriteLine( _
csvQuote(id) _
& "," & csvQuote(dtype) _
& "," & csvQuote(name) _
& "," & csvQuote(intname) _
)
End Sub
Rem *** Open and prime all Global Files
Sub openGlobalFiles(outputDir)
Set sheetsFile = openOutputFile(outputDir & "sheets.csv")
sheetsFile.WriteLine("SheetId, SheetName")
Set objectsFile = openOutputFile(outputDir & "objects.csv")
objectsFile.WriteLine("SheetId, ObjectId, ObjectType, Caption, HelpText")
Set dimensionsFile = openOutputFile(outputDir & "dimensions.csv")
dimensionsFile.WriteLine("ObjectId, DimensionType, DimensionName, InterfaceName")
Set expressionsFile = openOutputFile(outputDir & "expressions.csv")
expressionsFile.WriteLine("ObjectId, Parent, Expression")
Set actionsFile = openOutputFile(outputDir & "actions.csv")
actionsFile.WriteLine("ActionLocation, ActionLocationId, ActionType, ActionParameters")
Set fontsFile = openOutputFile(outputDir & "fonts.csv")
fontsFile.WriteLine("ObjectId, Font, FontElement, FontSize")
Set groupsFile = openOutputFile(outputDir & "groups.csv")
groupsFile.WriteLine("GroupName, GroupType, GroupField")
Set docinfoFile = openOutputFile(outputDir & "docinfo.csv")
docinfoFile.WriteLine("DocPath, DocOpenDuration, DocAnalysisDatetime, PrjUsed, GenerateLogfile, DaExtractQvVersion")
End Sub
You'll notice the extra line of logic in the extractDimensions sub. I added it for multiboxes. When a dimension in a multibox is renamed, that information is stored before the dimension name and type, and it does not following the ".//Title/v" pattern. From there, it's straight forward to tweak the Document Analyzer load script to pull in the interface names. I haven't played around with scraping the Interface Names from other objects, though I assume that it's possible.
Sources:
I looked at this article to play around with the XML xpaths:
https://msdn.microsoft.com/en-us/library/ms256086(v=vs.110).aspx
You can find Document Analyzer 2.8 here:
Document Analyzer V2.8 Update Available
Follow Up Question:
Is there a good way to scrape qlikview scripts to track how a field is renamed?
Happy hunting,
Margaret
Margaret,
You are my new development partner! I'm the author of Document Analyzer. I understand your requirement and I'm happy to integrate it into the next version. Please reach out to me at the contact form http://qlikviewcookbook.com/contact/ and we can collaborate on this.
Re your followup question:
"Is there a good way to scrape qlikview scripts to track how a field is renamed?"
That would be wonderful, wouldn't it? Complete field-level lineage. There is no simple way I know of. I'm aware of at least two vendors working on it, but don't know how far along they are in the process.
-Rob
Margaret,
You are my new development partner! I'm the author of Document Analyzer. I understand your requirement and I'm happy to integrate it into the next version. Please reach out to me at the contact form http://qlikviewcookbook.com/contact/ and we can collaborate on this.
Re your followup question:
"Is there a good way to scrape qlikview scripts to track how a field is renamed?"
That would be wonderful, wouldn't it? Complete field-level lineage. There is no simple way I know of. I'm aware of at least two vendors working on it, but don't know how far along they are in the process.
-Rob
Hi Margaret,
Dimension labels are now available in v3.2 of Document Analyzer. Download here:
Search Recipes | Qlikview Cookbook
-Rob
Super cool! Thank you for adding that!