# Vision File Explorer

**URL:** <https://forum.inductiveautomation.com/t/vision-file-explorer/41096>\
**Category:** Ignition\
**Tags:** ignition79\
**Created:** [December 1, 2020, 5:10pm UTC](https://forum.inductiveautomation.com/t/vision-file-explorer/41096 "2020-12-01T17:10:40Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![zxcslo](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/zxcslo/32/61610_2.png) [@zxcslo](https://forum.inductiveautomation.com/u/zxcslo)\
**Post date:** [December 1, 2020, 5:10pm UTC](https://forum.inductiveautomation.com/t/vision-file-explorer/41096/1 "2020-12-01T17:10:40Z")

</div>

The Reporting module has two components, File explorer and PDF Viewer, which are very useful also when you don’t use reporting.  
The customer wants to have the ability to display various documentation (.docx, .xlsx, .pdf, .txt) to the operators inside the Vision client on every production line. But they don’t need the Reporting module, because they have their own solution in place.  
The File Explorer component from the Reporting module is ideal for this situation (as we already have a license for Web Browser).  
When you use the File Explorer on the Vision window, the component displays “UNLICENSED Ignition REPORTING PLUGIN” overlay over the component.  
I know that PDF Viewer you can use without a license for the Reporting module, but not the File Explorer.

 ![IgnitionReportingFileExplorerUnlicensed](https://us1.discourse-cdn.com/inductiveautomation/original/3X/1/7/171671a6f537a0c7fbc844f7035ec7246f1788af.png)  
I’ve been searching the forum for the ‘alternative’ and found some suggestions to use the tree view component.  
I’m wondering how others solved this and if anyone can show an example of using Tree View like File Explorer. Pretty please…

---

<div class="post-metadata">

**Author:** ![schenk](https://avatars.discourse-cdn.com/v4/letter/s/6bbea6/32.png) [@schenk](https://forum.inductiveautomation.com/u/schenk)\
**Post date:** [December 2, 2020, 3:34am UTC](https://forum.inductiveautomation.com/t/vision-file-explorer/41096/2 "2020-12-02T03:34:05Z")

</div>

Check out [glob](https://docs.python.org/2/library/glob.html#module-glob) and [os](https://docs.python.org/2/library/os.html?highlight=chdir#module-os) modules for navigating the file system. I was doing something similar a while back (this was in a Windows environment) and came up with the following, which should get you started. I’m sure there are other ways of doing this, but I had plenty of other things to do and moved on after getting this to work 🙂

I created 2 custom properties on the root container named `pdfRootFolder`, and `selectedFilePath`. The selectedFilePath has this binding, which I then bound the File Path of the PDF Viewer to.

```auto
if(
	{Root Container.Tree View.selectedItem} > -1,
	{Root Container.pdfRootFolder} + '\\' + {Root Container.Tree View.selectedPath},
	''
)

```

I used a button to refresh the `items` in the tree view with the following code on `actionPerformed`.

```auto
import glob, os
pdfDirectory = event.source.parent.pdfRootFolder
os.chdir(pdfDirectory)
pdfFiles = glob.glob('*.pdf')

headers = ['path','text','icon','background','foreground','tooltip','border','selectedText','selectedIcon','selectedBackground','selectedForeground','selectedTooltip','selectedBorder']
data = [] 
for file in pdfFiles:
	path = ''
	text = file
	icon = ''
	background = 'color(255,255,255,255)'
	foreground = 'color(46,46,46,255)'
	tooltip = ''
	border = None
	selectedText = ''
	selectedIcon = ''
	selectedBackground = 'color(71,169,230,255)'
	selectedForeground = 'color(255,255,255,255)'
	selectedTooltip = '',
	selectedBorder = None
	data.append([path,text,icon,background,foreground,tooltip,border,selectedText,selectedIcon,selectedBackground,selectedForeground,selectedTooltip,selectedBorder])

event.source.parent.getComponent('Tree View').data = system.dataset.toDataSet(headers, data)

```

Hopefully that points you in the right direction.

---

<div class="post-metadata">

**Author:** ![zxcslo](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/zxcslo/32/61610_2.png) [@zxcslo](https://forum.inductiveautomation.com/u/zxcslo)\
**Post date:** [December 2, 2020, 11:58am UTC](https://forum.inductiveautomation.com/t/vision-file-explorer/41096/3 "2020-12-02T11:58:46Z")

</div>

This is what I ended up with:  
[TreeViewFileExplorer.mp4](https://drive.google.com/file/d/1yw_Qvk2yDkDJ7pyw490DDTXII0wfg4dz/view?usp=sharing)

In the ‘Choose Folder’ button ‘ActionPerformed’ event I have:

```auto
from javax.swing import JFileChooser

chooser = JFileChooser(event.source.parent.getComponent('txtPot').text)
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY)
chooser.setAcceptAllFileFilterUsed(False)
chooser.setDialogTitle("Select Folder")
if chooser.showOpenDialog(None) == JFileChooser.APPROVE_OPTION:
	event.source.parent.getComponent('txtPot').text = str(chooser.getSelectedFile())

```

In the ‘txtFolder’ propertyChange event I have:

```auto
if event.propertyName == 'text':
	treeView = event.source.parent.getComponent('Tree View')
	headers = system.dataset.getColumnHeaders(treeView.data)
	rows = []
	treeView.data = system.dataset.toDataSet(headers, rows)	#Emptying treeView
	rootPath = event.source.parent.getComponent('txtPot').text
	lblLoading = event.source.parent.getComponent('lblLoading')
	lblLoading.visible = True
	
	def longProcess(treeView=treeView, headers=headers, rows=rows, rootPath=rootPath, lblLoading=lblLoading):
		import os
		
		for path, dirs, files in os.walk(rootPath,topdown=True):
			for f in files:
				my_suffixes = (".docx",".doc",".xlsx",".xls",".pdf",".txt")
				if f.endswith(my_suffixes):
					filename, file_extension = os.path.splitext(f)
					#print filename, file_extension
					ikona = {
						'.docx' : 'Icons/docx.png',
						'.doc' : 'Icons/docx.png',
						'.xlsx' : 'Icons/xlsx.png',
						'.xls' : 'Icons/xlsx.png',
						'.pdf' : 'Icons/pdf.png',
						'.txt' : 'Icons/txt.png'}[file_extension]
					newRow = [
						path.upper(),
						f,
						ikona,
						"color(255,255,255,255)",
						"color(0,0,0,255)",
						"",
						"",
						"",
						ikona,
						"color(250,214,138,255)",
						"color(0,0,0,255)",
						"",
						""
						]
					rows.append(newRow)

		data = system.dataset.toDataSet(headers, rows)
		treeView.data = data
		lblLoading.visible = False
	
	system.util.invokeAsynchronous(longProcess) #Note that this is 'longProcess' instead of 'longProcess()'

```

In the ‘Refresh’ button actionPerformed event I have:

```auto
izbranapot = event.source.parent.getComponent('txtPot').text
event.source.parent.getComponent('txtPot').text = ""
event.source.parent.getComponent('txtPot').text = izbranapot

```

And in the ‘Tree View’ mouseClicked event I have:

```auto
if event.clickCount == 2:
	fileName = event.source.selectedPath
	if event.source.selectedItem > -1:
		system.net.openURL("file:///" + fileName)

```

In the end, it turned out just fine…  
Of course, any suggestions are more than welcome. 👍

---

<div class="post-metadata">

**Author:** ![zxcslo](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/zxcslo/32/61610_2.png) [@zxcslo](https://forum.inductiveautomation.com/u/zxcslo)\
**Post date:** [December 4, 2020, 11:12am UTC](https://forum.inductiveautomation.com/t/vision-file-explorer/41096/4 "2020-12-04T11:12:39Z")

</div>

OK, it turns out, that this solution won’t show the empty Folders (when there are no files in it).

 ![TreeViewEmptyFolder1](https://us1.discourse-cdn.com/inductiveautomation/original/3X/4/c/4c64c11270d7b55623c7722eb4a85fcf35ed86da.png)  
If I write by hand into the TreeView dataset just the Path then ‘Null 1’ is shown…  
 ![TreeViewEmptyFolder2](https://us1.discourse-cdn.com/inductiveautomation/original/3X/4/d/4d8fa983d71896cee4068431ab7878f98714e8ce.png)  
But our customer wants to show these empty folders also…  
Does anyone have an idea, how to do that?  
EDIT: That’s what I/we need: [Tree View Folder without a Node object? - #2 by Travis.Cox](http://forum.inductiveautomation.com/t/tree-view-folder-without-a-node-object/5905/2)

---

<div class="post-metadata">

**Author:** ![zxcslo](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/zxcslo/32/61610_2.png) [@zxcslo](https://forum.inductiveautomation.com/u/zxcslo)\
**Post date:** [December 4, 2020, 11:57am UTC](https://forum.inductiveautomation.com/t/vision-file-explorer/41096/5 "2020-12-04T11:57:01Z")

</div>

Please, vote.  
[ignition-features-and-ideas](https://inductiveautomation.canny.io/ignition-features-and-ideas/p/adding-a-folder-in-the-tree-view-without-any-children)
