12

I'm currently playing with ModelBuilder. I've added a picture of the model I have at the moment.

This model is currently iterating 6 shapefiles, so each of the 'output values' contain 6 figures in a list. I can't find a way to extract the values from these lists into a table/text file or similar.

Is there a way to do this?

model

This is what is shown when I open 'output values' after running the model: enter image description here

I just want to grab those 6 numbers somehow...

2
  • This is basically the same thing you are asking here correct? gis.stackexchange.com/questions/25922/… Collect values does just that. If you read the help it will tell you that it collects values that can be passed into another tool. So what are you trying to do with the values? Is it just log them to a file or do you need them for further processing?
    – theJones
    Commented May 23, 2012 at 19:42
  • I just want to log them to a file. I can't find a tool to feed the output values into in the model builder in order to extract them.
    – JPD
    Commented May 24, 2012 at 9:18

2 Answers 2

18

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:

  1. 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.
  2. 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.
  3. Save and close the inner model.

Outer Model - Runs inner model, runs Calculate Value tool just once when inner model completes:

  1. Create a new model -- this will be our "outer" model.
  2. Add a variable of type Folder to allow you to specify where to create the output CSV file.
  3. Add a variable of type String to allow you to specify the name of the output CSV file.
  4. 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)
  5. 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).
  6. Add the Calculate Value tool to the new model
  7. 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
    
  8. (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.

  9. (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: Inner Model

Outer 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.

6
  • Hello, thanks for putting so much effort into your reply and apologies for my late reply. I'm trying to run the model as you've described, but i'm having trouble with the CSV. I've made a blank CSV file in Excel and saved it, then loaded it into the model. ERROR 000539: Error running expression: multivaluesToCsv(r"%CSV File%", "%FC Name Values%", "%Minimum Values%", "%Average Values%", "%Maximum Values%") <type 'exceptions.IOError'>: [Errno 13] Permission denied: u'%CSV File%' Failed to execute (Calculate Value). I keep getting this error. My CSV is called CSVFile.csv.
    – JPD
    Commented May 30, 2012 at 14:29
  • 1
    Just fixed it - this is the perfect solution. Thanks so much for your help!
    – JPD
    Commented May 30, 2012 at 15:08
  • The Python code will create the CSV file for you, no need to create it beforehand. As you have seen though, if you open the file in Excel, that locks the file and it can't be written to by Python until you close it.
    – blah238
    Commented May 30, 2012 at 16:18
  • 2
    FYI I have updated the instructions and screenshots to use nested models to avoid Calculate Value running multiple times as well as fix the problem where the the text file had to exist beforehand (you now specify its output location and file name as two separate parameters).
    – blah238
    Commented Jun 7, 2012 at 6:42
  • Excellent answer! Helped me to solve a similar problem outputting Geostatistical Layer Cross Validation statistics to a csv file. Thanks @blah238! Commented Dec 20, 2016 at 22:39
1

The output that your model describes is simply a value updated in the attribute table is it not? Can you not simply open the .dbf file associated with the updated shapefile?

Failing this, Table Select (Analysis Tools > Extract) should work with an SQL query.

1
  • Hello, thanks for your reply. I'm afraid it doesn't update the .dbf file of each shapefile. Adding 'Table Select' to the model builder doesn't work either, as I can't connect either 'Minimum/Average/Maximum Distance' or 'Output Values' as an input for the tool.
    – JPD
    Commented May 23, 2012 at 14:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.