Select to view content in your preferred language

Text Element Questions

4069
34
Jump to solution
08-14-2013 11:36 AM
GeoffOlson
Regular Contributor
So I've got my text element function working in layout view, but it leaves me with two questions.  Can multiple rows be concatenated into the row.getValue or can it only find single fields?  Also, is it possible to return all feature records?

Here is the script I'm using to get the first result to fill the text box:

import arcpy  mxd = arcpy.mapping.MapDocument("Current") mapLyr = arcpy.mapping.ListLayers(mxd, "Detail_2013")[0]  concatElem = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", "concat")[0]  rows = arcpy.SearchCursor(mapLyr.dataSource) row = rows.next()  typeElem.text = row.getValue("CONCAT")  mxd.save() del mxd, row, rows,


Any suggestions a much appreciated.
Tags (2)
0 Kudos
34 Replies
T__WayneWhitley
Honored Contributor
I'm just thinking maybe the range function would apply here?

Since you know the total count couldn't you just run a loop, branching for the part of each half of the range?

In general, illustrated by:
>>> rowcount = 10
>>> for rows in range(rowcount):
 if rows in range(rowcount/2):
  print 'row ' + str(rows) + ' in range 1.'
 elif rows in range(rowcount/2, rowcount):
  print 'row ' + str(rows) + ' in range 2.'

  
row 0 in range 1.
row 1 in range 1.
row 2 in range 1.
row 3 in range 1.
row 4 in range 1.
row 5 in range 2.
row 6 in range 2.
row 7 in range 2.
row 8 in range 2.
row 9 in range 2.
>>> 
0 Kudos
MathewCoyle
Honored Contributor
I'm just thinking maybe the range function would apply here?


Yes that's a nice method when you know the number of columns. Would need a slight tweak for odd numbers of rows.
rowcount = 9
for rows in range(rowcount):
    if rows in range(rowcount / 2 + 1):
        print 'row ' + str(rows) + ' in range 1.'
    elif rows in range(rowcount / 2, rowcount):
        print 'row ' + str(rows) + ' in range 2.'


There was also this for a tool that can take a dynamic number of text columns (as long as they are already created and follow the naming/number convention).

import os
import arcpy


def main():

    layer_name = arcpy.GetParameterAsText(0)
    field = arcpy.GetParameterAsText(1)
    number_columns = float(arcpy.GetParameterAsText(2))

    mxd = arcpy.mapping.MapDocument("Current")
    mapLyr = arcpy.mapping.ListLayers(mxd, layer_name)[0]

    rowcount = int(arcpy.GetCount_management(layer_name).getOutput(0))
    percolumn = round(rowcount / number_columns)

    text_var = str()
    item_count = 0
    column_count = 1
    for row in arcpy.SearchCursor(mapLyr.dataSource, sort_fields='{0} A'.format(field)):
        text_var += '{0}{1}'.format(row.getValue(field), os.linesep)
        item_count += 1
        column = 'concat{0}'.format(column_count)
        arcpy.AddMessage(item_count)

        if item_count == percolumn and column_count != number_columns:
            arcpy.AddMessage('next column')
            arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", column)[0].text = text_var
            text_var = str()
            column_count += 1
            item_count = 0

    arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", column)[0].text = text_var

    arcpy.RefreshActiveView()
    mxd.save()
    del mxd

    arcpy.AddMessage("First column should have : {0} rows.".format(percolumn))  #used to check that it calculated properly

if __name__ == '__main__':
    main()

0 Kudos
GeoffOlson
Regular Contributor
Thanks for all the help, guys!  I have the if statement almost working.  The second column works fine, but the first column is only returning the last result.  I have a field that numbers each row in the table, besides the FID, so that way on each map page each row of text is numbered and it matches the label in the map.  Instead of using a counter += 1, can an attribute field be used instead?  I have the field "Crash_Num" that numbers each feature in the map for each page but I don't know how to use a searchcursor and getValue.
0 Kudos
T__WayneWhitley
Honored Contributor
Are you using Mathew's code?  (If so, you should award him points and/or the answer when you finally get things running.)

As 'extra' help, this is where the row from your table value for the 'field' is passed (from Mathew's last posted code):
for row in arcpy.SearchCursor(mapLyr.dataSource, sort_fields='{0} A'.format(field)):
        text_var += '{0}{1}'.format(row.getValue(field), os.linesep)


EDIT:
Actually, in that 1st line above, all your table fields are being passed in, just that the one specified as 'field' (assigned at the SetParam statement at the beginning) is used for sorting.

So you could 'look up' other field values by inserting a line within the loop such as:
aNewTxtVar = row.getValue('yourDesignatedFieldname')


(see getValue for the SearchCursor in the webhelp)
Anyway, hope that helps!

Enjoy,
Wayne
0 Kudos
GeoffOlson
Regular Contributor
I think I just got it working.  Here's the final script:

import arcpy, os

mxd = arcpy.mapping.MapDocument("Current")
mapLyr = arcpy.mapping.ListLayers(mxd, "Detail_2013")[0]

concatElem1 = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", "concat1")[0]
concatElem2 = arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT", "concat2")[0]

rowcount = int(arcpy.GetCount_management("Detail_2013").getOutput(0))
percolumn = round(rowcount / 2.0)
count1 = 1
count2 = rowcount

rows = arcpy.SearchCursor(mapLyr.dataSource)

text_var1 = str()
text_var2 = str()

for row in rows:
    if count1 <= percolumn:
        text_var1 += '{0}{1}'.format(row.getValue("CONCAT"), os.linesep)
        concatElem1.text = text_var1
        count1 += 1
    elif count2 > percolumn:
        text_var2 += '{0}{1}'.format(row.getValue("CONCAT"), os.linesep)
        concatElem2.text = text_var2
        count2 - 1
    else:
        pass
mxd.save()
del mxd, row, rows,
0 Kudos
GeoffOlson
Regular Contributor
The only problem I have now is the script isn't following the page definition query.  Only the queried features appear in the attribute table, but the script lists all features, even the ones that are queried out.
0 Kudos
T__WayneWhitley
Honored Contributor
Well you have options - that's the good news.  The searchcursor input parameter works on a layer (the 1st param)...or you could optionally enter a query filter...see the syntax and explanation at the link below:

usage:
SearchCursor (in_table, field_names, {where_clause}, {spatial_reference}, {explode_to_points}, {sql_clause})

http://resources.arcgis.com/en/help/main/10.1/index.html#//018w00000011000000


oops, that one was for the da (data access) search cursor.... you need this one:


SearchCursor (dataset, {where_clause}, {spatial_reference}, {fields}, {sort_fields})

http://resources.arcgis.com/en/help/main/10.1/index.html#//018v00000050000000
0 Kudos
GeoffOlson
Regular Contributor
Using a SearchCursor should filter out which rows are being returned?  Can multiple row.getValue functions be used?  I was concerned the "for row from rows:" would have assigned a value to row and couldn't be used twice, and a different variable be created in place of row?

Manually setting a definition query also fails to limit which rows get searched.
0 Kudos
T__WayneWhitley
Honored Contributor
You should post your code and any error msgs you're receiving...

In short, yes you can get another field value from the row object.
Incidentally, you could say 'for browncow in rows' and you are still implicitly getting a row object from the cursor.  (why simply using 'row' is often used)

I suspect your where_clause query is faulty, but have no idea since there's no posted code, etc.  Don't forget to post the error msg too!
0 Kudos
GeoffOlson
Regular Contributor
I added this to get the page name:

pageNum = arcpy.GetParameterAsText(0)
ddp = mxd.dataDrivenPages
arcpy.AddMessage(pageNum)
pageID = mxd.dataDrivenPages.getPageIDFromName(str(pageNum))
mxd.dataDrivenPages.currentPageID = pageID


and I changed the SearchCursor to this:
rows = arcpy.SearchCursor(mapLyr.dataSource, "PageID = \'Intersec\'")


but I get an error saying the fields in the search cursor do not exits.  I'm trying to set the field value to the page name.  The other thing that happens is the page name seems to only be stored as a page number and not the specified index layer field.
0 Kudos