Filter Data Source for Table View (AppleScript Studio)

This handler filters a data source for an AppleScript Studio project. It should be easy to change what column(s) it searches, and whatever sorting you want to use.

OS version: OS X

-- filter - string to search for
-- theTable - the table view which displays the data source
-- theFullDS - the unfiltered data source
on filterDataSource(filter, theTable, theFullDS)
	try
		delete data source "filtered"
	end try
	if filter is not "" then
		set theDS to make new data source at end of data sources with properties {name:"filtered"}
		repeat with i in every data column of theFullDS
			set theCol to make new data column at end of data columns of theDS
			tell theCol
				set name to name of i
				set sort type to sort type of i
				set sort case sensitivity to sort case sensitivity of i
				set sort order to sort order of i
			end tell
		end repeat
		repeat with i in every data row of theFullDS
			--change next line if you want to filter multiple data cells or a different data cell.
			if contents of data cell 1 of i contains filter then
				set theRow to make new data row at end of data rows of theDS with properties {associated object:(associated object of i) as string}
				repeat with j from 1 to count of every data cell of i
					set name of data cell j of theRow to name of data cell j of i
					try
						set contents of data cell j of theRow to contents of data cell j of i
					end try
				end repeat
			end if
		end repeat
		set sort column of theDS to data column 1 of theDS
		set sorted of theDS to true
		set data source of theTable to theDS
	else
		set data source of theTable to theFullDS
	end if
	update theTable
end filterDataSource

Hello fellow scripters,
First I would like to thank the original author of this script - it helped me immensely. Secondly, I wanted to share my changes/tweeks to this script.

My goal was to create an AppleScript SEARCH-AS-YOU-TYPE kind of search of the contents of a table so the results would quickly be funneled down visually. I put together this test application (built from what was originally Jonathan Nathan’s “get_rows” example - because I also wanted to get data on the selected rows of the found set of data, thanks Jonathan!). The entire XCode project can be downloaded here:

http://www.beebeography.com/software/openSourceExamples/SearchATableAsYouType.zip

In a nutshell the example will randomly populate the bottom table with data and:

  • If text is typed in the search field it will display all matches in the top table

  • The search is performed as you type and the results are updated as you go :slight_smile:

  • Additional buttons exist to show how to programatically:
    * Set the selected rows
    * get the selected rows (a list of numbers)
    * get the selected data rows (a list of references to the data row)
    * Scroll to a row - forces the table to show it if it is not visible

The two chunks of code in the XCode project that do the work are:


-- Here is where the user initiates the search by typing in a text field named "searchField"
on action theObject
	if name of theObject is "searchField" then
		if searchAction is false then -- we are not already performing another search
			set searchAction to true -- tell the app we are now performing a search
			
			--	GET THE DATASOURCE TO BE SEARCHED
			set theFullTable to table view 1 of scroll view "with_ds" of window "main"
			set theFullDS to data source of theFullTable
			
			--	GET THE TABLE USED TO DISPLAY THE FOUND SET
			set theFilteredTable to table view 1 of scroll view "without_ds" of window "main"
			set theFilteredDS to data source of theFilteredTable
			
			--	GET THE FILTER CRITERIA
			set theFilter to contents of text field "searchField" of window "main"
			--	COMPARE THIS TO PREVIOUS SEARCH CRITERIA
			set a to (count of currentSearchCriteria)
			set b to (count of theFilter)
			if (a > 0) and (b > a) then
				set theTest to (characters 1 thru a of theFilter) as string
				if (theTest is currentSearchCriteria) and (searchStatus is true) then
					beep
					set theFullDS to theFilteredDS
				end if
				log theTest
			end if
			set currentSearchCriteria to theFilter
			
			if theFilter is not "" then -- we have something to search for
				log "theFilter = " & theFilter
				my filterDataSource(theFilter, theFilteredTable, theFullDS)
			else
				set data source of theFilteredTable to theFullDS
			end if
		end if
		set searchAction to false -- tell the app we are no longer performing a search
	end if
end action



-- theFilter - string to search for
-- theTable - the table view which displays the data source
-- theFullDS - the unfiltered data source
on filterDataSource(theFilter, theTable, theFullDS)
	tell progress indicator "progressWheel" of window "main" to start
	
	set searchStatus to false -- tell the app we are currently performing a search
	--set theCount to count of data sources of me
	--log (theCount as string) & " data sources of me"
	
	--	WE NEED TO DELETE DATA SOURCES WE ARE NO LONGER USING
	--	WE KEEP X AROUND IN CASE WE NEED TO SEARCH IT AS A SUBSET
	try -- Clean Up - delete the filtered datasource x-1 since we no longer need it
		delete data source ("filtered" & ((x - 1) as string))
	on error
		log "could not delete data source named " & ("filtered" & ((x - 1) as string))
	end try
	
	set x to x + 1 -- we use x to increment the filtered data source name so we can identify the ones currently in use
	
	if (theFilter) is not "" then -- we have something to search for
		--	CREATE THE DATASOURCE TO STORE THE FOUND RESULTS
		--	BUILD IT USING THE PROPERTIES OF THE DATABASE WE ARE SEARCHING (DUPLICATE THE STRUCTURE)
		set theDS to make new data source at end of data sources with properties {name:"filtered" & x as string}
		repeat with i in every data column of theFullDS
			set theCol to make new data column at end of data columns of theDS
			tell theCol
				set name to name of i
				set sort type to sort type of i
				set sort case sensitivity to sort case sensitivity of i
				set sort order to sort order of i
			end tell
		end repeat
		set update views of theDS to false
		
		--	ASSIGN THE NEWLY CREATED DATASOURCE TO THE TABLE VIEW
		set sort column of theDS to data column 1 of theDS
		set sorted of theDS to true
		set data source of theTable to theDS
		
		set localSearchCount to globalSearchCount
		
		try
			append theDS with (contents of data cells of (data rows of theFullDS whose ((contents of data cell 2 of it contains theFilter) or (contents of data cell 3 of it contains theFilter))))
		on error theError number theNumber
			log theError & tab & theNumber
		end try
		
		tell progress indicator "progressWheel" of window "main" to stop
	end if
	
	update theTable
	
	set searchStatus to true
end filterDataSource

There are a couple of bugs/issues with the above code, and I updated/improved the search functionality even further, providing a much more robust solution than the one mentioned above, in my iTunes remote application (source code found here - http://www.beebeography.com/remoteitunes/index.html). The version I used in the iTunes remote only uses one table - when a search is performed it will replace the table contents with the found set (keeping the original data safe behind the scenes). If the search is canceled the original full set of data is reinstated in the table view. Unfortunately the code is harder to separate from the rest of the application so if you want to see how it works download the source code and scroll to the very bottom of the script named “iTunes Remote.applescript” - there is a section labeled “FILTER_METHODS” that holds the bulk of it.

I hope someone finds this useful, if you have any questions or comments they would be greatly appreciated!
jON bEEBE

Very nice :slight_smile:

I too write an open source iTunes remote control app (TuneConnect, http://www.tuneconnect.net), and if you don’t mind I think I’ll take a look into implementing this in my track browser.

Feel free to download my source code and take a look through it-- see if you can find anything you can use. It’s not modeled after iTunes like so many remote control apps, but instead has two windows: an iTunes-like mini-player to control the music, which features a search box to play a song if you know what you’re looking for, and a track browser that is similar to the iTunes interface.

Thanks for the script!

-Matt