You can do this using the Calculate Value (Data Management) tool and some Python magic. See also this related question: Add arbitrary code to Arcgis model builder?
A multivalue variable is just a semicolon-delimited string of values, so what the multivaluesToCsv
function below does is split the multivalue variables into lists and transpose them into rows which are then written to a CSV (comma-separated value) text file.
Model iterators run ALL the processes in the model once per iteration -- this is undesirable for our Calculate Value tool, which we just want to run once at the end. The way you accomplish this is by creating another, outer model to wrap the original, inner model. This is discussed in the help topic Integrating a model within a model.
So here's what you need to do to get this working:
Inner Model - Iterates feature classes, processes them, collects values:
- In your original model, which will be our "inner" model, add another Collect Values tool to collect the
Name
variable's values so that we can map the distance statistic values to their corresponding feature class names.
- Expose the input and output variables as model parameters (right-click an oval and check Model Parameter). Do this for each of the outputs of the Collect Value tools as well as whatever input parameters you need such as the Input Workspace.
- Save and close the inner model.
Outer Model - Runs inner model, runs Calculate Value tool just once when inner model completes:
- Create a new model -- this will be our "outer" model.
- Add a variable of type
Folder
to allow you to specify where to create the output CSV file.
- Add a variable of type
String
to allow you to specify the name of the output CSV file.
- Add the Inner Model to the new model (drag and drop from ArcToolbox or right-click and Add Data or Tool, browse to the inner model and click Add)
- Create variables for any parameters of the inner model you want to be able to set from the outer model, such as the Input Workspace (right-click the inner model and and choose Make Variable-From Parameter).
- Add the Calculate Value tool to the new model
Paste the following into the appropriate boxes of the Calculate Value tool:
Expression:
multivaluesToCsv(r"%Output CSV File Location%", "%Output CSV File Name%", "%Feature Class Names%", "%Minimum Distance Values%", "%Average Distance Values%", "%Maximum Distance Values%")
- This uses in-line variable substitution to pass the model variables into the function. Adjust to match your model variable names.
- The
r
before "%Output CSV File Location%"
is significant: this indicates that this is a raw string; because Windows file system paths usually contain backslashes (an escape character in Python), we have to use this to prevent Python from misinterpreting the backslashes and subsequent characters as special character sequences.
- Be sure to put quotes around the in-line variables because without them Python will think they are identifiers instead of strings.
Code Block:
import os, csv
def multivaluesToCsv(csvfilepath, csvfilename, fcnames, minvalues, avgvalues, maxvalues):
ext = 'csv' # Define output file extension (e.g. csv or txt)
header = ['FC', 'MIN', 'AVG', 'MAX'] # Define header row (column names)
# Join CSV file path and name, adding extension if necessary
csvfile = os.path.join(csvfilepath, os.extsep.join((csvfilename, ext)) if not os.path.splitext(csvfilename)[1].lower().endswith(ext) else csvfilename)
# Open text file for writing
with open(csvfile, 'wb') as f:
w = csv.writer(f)
w.writerow(header) # Write header row
rows = zip(*map(lambda x: x.split(';'), [fcnames, minvalues, avgvalues, maxvalues])) # Transpose the semicolon-delimited values into rows
w.writerows(rows)
return csvfile
(Optional) Expose the input and output variables as model parameters if you want to be able to run them from the model's tool dialog or chain it together with other models/scripts. The sole output of the outer model is the CSV file.
- (Optional) Connect the input variables and inner model outputs to the Calculate Value tool as preconditions. I do not think this actually has any effect, it just makes it more clear visually as to what's going on.
I have tested this with ModelBuilder and got it working (see screenshots).
Inner Model:
Outer Model:
The inner model runs all of its processes once per feature class, and then the Calculate Value tool runs once at the end to output the CSV file once and only once.