Select to view content in your preferred language

Modelbuilder: Inline variable %Workspace% not working with Workspace Iterator

7533
10
04-23-2014 09:12 AM
LukeFloch
Occasional Contributor
I have 30 gdbs with identically named features in different geographic zones. I'm trying to run the same tasks on each by iterating through each gdb in a folder. However, when I try to use the %Workspace% inline variable in the model it gives me an error that the FC does not exist when I try to run it. If I pull the iterator out and replace it with a single gdb from the folder and name it "Workspace" the model runs just fine.

Attached is a trimmed down version of the model with just the first process being run, where the pathname for Wilderness = %Workspace%\Wilderness

Hopefully there's something simple I'm just missing because I haven't used this before. Thanks
0 Kudos
10 Replies
AmyKlug
Frequent Contributor
Wouldn't you use %name% as the in-line variable?
0 Kudos
LukeFloch
Occasional Contributor
Wouldn't you use %name% as the in-line variable?


Tried that as well, same error
0 Kudos
AmyKlug
Frequent Contributor
Reading your model it looks as though you are trying to append an empty feature class to a feature class that might not exist in the location specified.
0 Kudos
T__WayneWhitley
Honored Contributor
It's not entirely clear to me what you're trying to do - are you trying to take all the layers by the same name (representing different zones) in different workspaces (same folder) and merge those features into a single feature class?  If so, you could iterate the workspaces as you are doing and use Collect Values to then feed the multivalue list to the Merge tool.  See this:

http://resources.arcgis.com/en/help/main/10.2/index.html#/Examples_of_using_Model_Only_tools_in_Mode...


Wayne
0 Kudos
LukeFloch
Occasional Contributor
In essence what I'm trying to do is an erase using 21 feature classes that must be erased in a specific order. That order can change, meaning all 30 zones have to be run again, which is why I'm trying place it in a model where I can just rearrange the order and then hit go. I've attached a quick example to show what works and what doesn't along with the error I get.

In both models the paths for the FCs are:

%Workspace%\FC1
%Workspace%\FC2
%Workspace%\FC3

In the works.jpg I simply placed the gdb in the model and renamed it "Workspace"
In does not work.jpg I placed the workspace iterator in the model, using the folder the gdb is in, and I get the error that the files do not exist.
0 Kudos
AmyKlug
Frequent Contributor
You need to add "iterate feature class" to your model. Problem is you can only have one iterator per model. so you need to create a model in a model. create a model with iterate workspace and save it. use the name and workspace output fields as parameters to use in the 2nd model. see attached

You had your iterate workspace attached to the rest of the model as a precondition (noted by dashed lines). all that means is that the precondition has to run first and was not connected to the rest of your model. the erase tool needs to be connected to a feature class, not a workspace.

You can rename the workspace name (name (2)) variable by right clicking. you might not want 2 variables with the same name. so if you renamed it WorkspaceName you would use %WorkspaceName% as your in-line variable substitution

Parse Path might help you too for path names as variables:
http://resources.arcgis.com/en/help/main/10.1/index.html#//004000000008000000
0 Kudos
T__WayneWhitley
Honored Contributor
I don't know if you're still working on this but think I found an easy solution - it occurred to me (maybe I'm wrong) that you just needed a little intervention to actually set the workspace from the iterator.  I'm used to doing this via python, so I cheated a little and entered a small snippet:
import os, arcpy
workspace = arcpy.GetParameter(0)
 
# set output param
arcpy.env.workspace = workspace
arcpy.AddMessage('The set workspace is: {0}'.format(arcpy.env.workspace))


So with a minor modification of the basic structure of your model, I got this to run (see the attached) -- I'm getting empty output which is correct based on the 2 inputs I fed in for the Erase (I only used one erase; concept is the same).

I notice you just have to be careful copying model components around - the ModelBuilder environment likes to source things sometimes in a funny way.....at the start it should be sourced to your Default gdb, otherwise it may falter in the validation cycle which kicks off before any model processes get launched.  That's what you were running into before, with the "this or that doesn't exist" messages.  I believe I made everything relative-pathed so that you can copy the folder to your local drive, then open the model for editing and set your own params.  May have to set up some valid layer initialization to get past the internal validation, but that should be no big deal - let me know if you have any difficulty.

Hope that helps.



Enjoy,
Wayne
0 Kudos
LukeFloch
Occasional Contributor
Thanks Wayne,

I think I see what you're trying to do there. I gave it a go but it still didn't solve the problem of modelbuilder not recognizing the workspace as a location for an inline variable. I noticed your testlyr pointed to your default gdb. when I changed it to include the workspace as an inline variable %Workspace%\testlyr (but using my own layer ans workspace of course) the same error came up, that the feature does not exist. It seems like arc, instead of just running the model and using the currently iterated workspace to find the layer, is getting hung up in the validation on the fact that since it hasn't iterated to a workspace yet then the features within that workspace must not exist.

Is there a way, in your python script, to have it output the workspace to a variable representing the gdb within the folder that the iterator is using (in the model I suppose it would represent the first gdb, but then would change to match whatever gdb is being iterated)? That way arc can "see" a gdb and believe that the features exist? Either that or if there's a way to tell it to skip the validation and say "Yes, I know you can't see the features yet, but once the iterator defines the workspace they'll be there, so just start running."

Thanks for your help on this.

Edit: I also tried using parse path for the inline, to no success.
0 Kudos
T__WayneWhitley
Honored Contributor
Hmmm, I apologize - that did not work as anticipated.  As a kind of stopgap, I made a tiny script tool that should do what you want - just like a model, you can open it to edit it if you don't mind moving params around within a text editor (or input them at the interface in different order).  This assumes you have fcs (fc1, fc2, and fc3) in each gdb, with no error trapping.  I think it's pretty self-explanatory and I set up the input params on the tool to be AnyValue so that the validation is defeated (sorry ESRI)....so in this case you'd only enter the fc name (not including the path to the workspace).

I'd like to take a look at the ModelBuilder solution again later...I think I have a better solution, but it's not been tested yet.

See the attached - the script referenced by the tool is below, and of course anything not clear to you, let me know.
import os, sys, arcpy

# get params
folder = arcpy.GetParameterAsText(0)
fc1 = arcpy.GetParameterAsText(1)
fc2 = arcpy.GetParameterAsText(2)
fc3 = arcpy.GetParameterAsText(3)

# your 1st and 2nd stage erase outputs
output = arcpy.GetParameterAsText(4)
testout = arcpy.GetParameterAsText(5)

# list and iterate the gdbs
arcpy.env.workspace = folder
gdbs = arcpy.ListWorkspaces(workspace_type='FileGDB')
arcpy.AddMessage(str(gdbs))

for gdb in gdbs:
    arcpy.env.workspace = gdb
    arcpy.Erase_analysis(fc1, fc2, output)
    arcpy.Erase_analysis(output, fc3, testout)
    arcpy.AddMessage('completed erase for {0}'.format(gdb))


Again, sorry for the misunderstanding --- I think knowing what I know now about ModelBuilder behavior I'm going to test an embedded model for the Workspace iterator and use Collect Values to create a multivalue output parameter, then use a For iterator (or Multivalue iterator) to loop on the pathnames to execute each Erase.  Not sure, but I think the internal validation will not trip up this approach.

Wayne
0 Kudos