I am an old VB/VB.Net guy and this one has me stumped in terms of building a tool using model builder so any assistance in leading me to a solution will be greatly appreciated. (I can build a vbs script to this but I am attempting to do this within modelbuilder/python script [if necessary])
Background:
I work for a transportation agency. Our GIS field collection is based upon new construction projects. For any project, all of our GIS layers are extracted that fall within a buffered distance of the project along with all the attributes that are associated with the objects. I felt that this would be a great place to use modelbuilder to make a tool that would do this so my tech's that have no SQL experience can quickly create a MS Access Field Geodatabase. Old method was to manually export each layer (a process that could take upwards to a week to complete.
I completed 99.9% of the problem within the model and it can create the field database in a matter minutes. However..... I have one small problem.
Our traffic signs are stored in the database as two objects: 1. Sign support (GIS point feature class) 2. SignPanels which is an independent tabular table. The linkage between both objects is the SignSupportID which is the primary key in the Sign Support layer and foreign key in the tabular table.
Problem:
I would like to create/copy tabular table of specified fields from the SignPanels table that have a matching Sign Support ID from the Sign support GIS layer (This is a filtered set containing the sign support points within the project area)... This seems to be a simple common problem but I have hit wall....
Manually, I would simply create an sql statement selecting those SignPanels that were "in" the filtered sign support gis layer table. Select * from SignPanels SP where SP.SupportID in (Select SupportID from SignSupports where Project = "XXXXX")
Solution or Methodology needed:
.. using Model builder I need a Feature Class and Tabular Table along with a query that can iterate through the FC for all the ID's ...) I already have the Filtered GIS layer as an output in the model. What I now need is to create a table containing my desired attributes of only those panels in the SignPanels table that have a support id that matches the Filtered GIS layer.
Confused? Any Ideas?
Thanks ahead of time!
Ted
Solved! Go to Solution.
Tool gives me an error on the input layer or table view parameter ...
file:///C:/Users/tkowal/AppData/Roaming/ESRI/Desktop10.2/ArcToolbox/Dlg/MdDlgContent.htm#ERROR file:///C:/Users/tkowal/AppData/Roaming/ESRI/Desktop10.2/ArcToolbox/Dlg/MdDlgContent.htm#
updateMessage Execution Error: Runtime error Traceback (most recent call last): File "D:\Workspace\MaintUpdate\ProjGIS\KeyfileSelection.tbx#KeyfileSelection.UpdateMessages.py", line 4, in File "D:\Workspace\MaintUpdate\ProjGIS\KeyfileSelection.tbx#KeyfileSelection.UpdateMessages.py", line 31, in updateMessages AttributeError: DescribeData: Method fidset does not exist
The panels table does not have an OID or FID; this is not a GIS table but a regular run of the mill tabular table in a database with its own Primary Key other than an OID that ESRI insists upon. Too many other processes use this table to change its structure.
OK, my tool requires OID behavior, but you could try stringing a workflow together in Modelbuilder and precede the tool with a Make Query Table process that dummies up an OID in memory.
regards
Same error even using the dummy up make table query.
I even tried a perpared mdb with all the tables having an OID. Same error!
The error is in the tool validation, it looks to be caused by the workspace not supporting selection, is the MDB a Personal Geodatabase or a vanilla Access database? The tool requires a GDB.
BTW -- I am on 10.2.2 Don't know why the script did not work. I ran it in idle using the same DB I sent you, I even went as far as creating the same temp locations.... Still the same error. Re-created the Geodatabase ... with OID's (Esri recognized!) Still the same error. Harolds tool -- the MS Access is a personal geodatabase -- however the sign panels are a link to another base pure data. But the test I am doing for automation, it is not a link but a real table with OID's..... This project was to try and acomplish 100% automation for creating a field datase for GIS collection. The techs that would run it have little to no DB/GIS experience -- basically Facebooker's !
I am not a lover of Python because of the reasons I am experiencing -- very temperamental and inconsistant compared to VBA or VB.Net --- there I could trap problems/ repeat them etc.... Seems like I am taking a sledge hammer to perform a very basic sql query .... in any event I got another methodology to work using Select LayerByAttribute_management and building the select clause.
I still would be interested in figuring out why both Blake and Bruce script/tool was failing (for competeness sake!)
The Script I got to work in my model and my ESRI setup :
import arcpy, os # Local Variables OriginTable = arcpy.GetParameterAsText(0) #Sign Support --> Make Table View DestinationTable = arcpy.GetParameterAsText(1) #Sign Panels ---> Make Table View PrimaryKeyField = arcpy.GetParameterAsText(2) #SupportID /Sign Support ForiegnKeyField = arcpy.GetParameterAsText(3) #SupportID /Sign Panels def buildWhereClauseFromList(OriginTable, PrimaryKeyField, valueList): """Takes a list of values and constructs a SQL WHERE clause to select those values within a given PrimaryKeyField and OriginTable.""" fieldDelimited = arcpy.AddFieldDelimiters(arcpy.Describe(OriginTable).path, PrimaryKeyField) # Determine field type fieldType = arcpy.ListFields(OriginTable, PrimaryKeyField)[0].type # Add DBMS-specific field delimiters # Add single-quotes for string field values if str(fieldType) == 'String': valueList = ["'%s'" % value for value in valueList] # Format WHERE clause in the form of an IN statement whereClause = "%s IN(%s)" % (fieldDelimited, ', '.join(map(str, valueList))) arcpy.AddMessage(whereClause) return whereClause def selectRelatedRecords(OriginTable, DestinationTable, PrimaryKeyField, ForiegnKeyField): """Defines the record selection from the record selection of the OriginTable and apply it to the DestinationTable using a SQL WHERE clause built in the previous definition""" # Set the SearchCursor to look through the selection of the OriginTable sourceIDs = set([row[0] for row in arcpy.da.SearchCursor(OriginTable, PrimaryKeyField)]) # Establishes the where clause used to select records from DestinationTable whereClause = buildWhereClauseFromList(DestinationTable, ForiegnKeyField, sourceIDs) # Process: Select Layer By Attribute arcpy.SelectLayerByAttribute_management(DestinationTable, "NEW_SELECTION", whereClause) # Process: Select related records between OriginTable and DestinationTable selectRelatedRecords(OriginTable, DestinationTable, PrimaryKeyField, ForiegnKeyField) #output same as Destination Table
Another note.... The script even honors the db link to another database where the real resides... go figure I would have sworn the script choke on that!
Sorry for all the trouble but I'm glad you got something to work!
Thanks for your help. I still wonder why the script worked on your system/set and not mine -- it appears that we are running the same versions. I am still keeping your script for future investigation/testing --- It is well written! Ted