2

I am using ArcMap 10.3. This question involves the use of tables and personal geodatabase features.

I am looking for an efficient way to populate Water Meter fields using data from a Table.

The table contains all of the billing information for the water meters.
The water meters layer only contains the physical location and blank fields awaiting the billing information.

I am seeking a way to highlight a single water meter feature from a layer (output/destination), highlight a single row from the table (input), run the Model and have the data from the highlighted row in the table be appended to the water meter feature.

The data I am looking to copy is three fields, all in String/Text format.

(Yes, the point is to do this one at a time with hand-selected data)
(Yes, there are better ways to accomplish my end-goal, but this is the method I need right now)

  • There is no built-in functionality to do this. I don't think that Python can detect highlighted rows in a layer or table. Even ArcObjects has a hard time with highlighted rows. I would rethink this workflow. There is no field or set of fields to relate the 2 together? – Richard Fairhurst May 19 '16 at 17:23
  • @RichardFairhurst That is unfortunate news. No, the meters layer is completely void of information that could be used to link the two together. I was hoping to avoid typing it all in by hand, but I may have to resort to that. – Nomkins May 19 '16 at 18:02
  • 1
    I would just add a LINK field to the meters table and simply copy/paste the ObjectID value or other Unique ID value of the point record you would have highlighted to the record in the meters table that you would have highlighted. Just right click on the ObjectID/Unique ID field itself and press Copy. Then put your cursor in the Link field of the table and paste the value directly. That should be less effort than retyping 3 fields. Then an updatecursor script could easily be written to transfer all of the data. Or just join and export to add the table fields to the points. – Richard Fairhurst May 19 '16 at 18:13
  • @RichardFairhurst Definitely would be less work to only manually do one field for all meters and then auto-populate the rest later on. – Nomkins May 19 '16 at 18:21
  • Since you are open to this approach I have made it my answer and added the basic script I would use to do the data transfer after the LINK field values are populated. – Richard Fairhurst May 19 '16 at 18:33
3

There is no built-in functionality to do this. I don't think that Python can detect highlighted rows in a layer or table. Even ArcObjects has a hard time with highlighted rows. I would rethink this workflow.

I would just add a LINK field to the meters table and simply copy/paste the ObjectID value or other Unique ID value of the point record you would have highlighted to the record in the meters table that you would have highlighted. Just right click on the ObjectID/Unique ID field itself and press Copy. Then put your cursor in the Link field of the table and paste the value directly. That should be less effort than retyping 3 fields. Then an updatecursor script could easily be written to transfer all of the data. Or just join and export to add the table fields to the points.

See my blog on Turbo Charging Data Manipulation with Python Cursors and Dictionaries for a script that can do the transfer once the LINK is set up. This script should be easy enough to adapt to your data:

import arcpy  

sourceFC = r"C:\Path\SourceTable"  

sourceFieldsList = ["LINK", "Value1Field", "Value2Field", "Value3Field"]  

# Use list comprehension to build a dictionary from a da SearchCursor  
valueDict = {r[0]:(r[1:]) for r in arcpy.da.SearchCursor(sourceFC, sourceFieldsList)}  

updateFC = r"C:\Path\UpdateFeatureClass"  

updateFieldsList = ["OID@", "Value1Field", "Value2Field", "Value3Field"]  

with arcpy.da.UpdateCursor(updateFC, updateFieldsList) as updateRows:  
    for updateRow in updateRows:  
        # store the Join value of the row being updated in a keyValue variable  
        keyValue = updateRow[0]  
         # verify that the keyValue is in the Dictionary  
        if keyValue in valueDict:  
             # transfer the value stored under the keyValue from the dictionary to the updated field.  
            updateRow[1] = valueDict[keyValue][0]  
            updateRows.updateRow(updateRow)  

del valueDict 

The script assume you have a one to one (1:!) relationship between the features and the meters. If you have a one to many (1:M) relationship it may be easier to have both in the same geodatabase, join them and export the result to multiply the points to make the relationship 1:1. Then the field values of the table can be moved to the point fields and drop the duplicate table fields.

2

While I agree that @RichardFairhurst's answer is the quicker and better way to do it, it is actually possible to make the selection of a meter and selection of a table record and have the meter update from the table the way you describe it in your question.

import arcpy

tblview = arcpy.mapping.TableView('WaterMeterTable')
featlyr = arcpy.mapping.Layer('WaterMeters')

# List of field names in Table that you want to copy to water meter layer
tblFields = ['MeterNumber', 'MeterType'] 
# List of field names in water meter layer that you want populated by table.  Match the same order as the table fields above.
lyrFields = ['MeterNumber', 'MeterType'] 

# Get a list of selected records in the table
tblsel = tblview.getSelectionSet() 
# Get a list of the selected features in the water meter layer
lyrsel = featlyr.getSelectionSet() 

if len(tblsel) == 1 and len(lyrsel) == 1: # If there is a single record/feature selected, then proceed, otherwise bail
    # Query for Search Cursor to find the selected record
    tblExpression = 'ObjectID = {}'.format(tblsel[0]) 
    # Query for Update Cursor to find the selected feature
    lyrExpression = 'ObjectID = {}'.format(lyrsel[0]) 
    with arcpy.da.SearchCursor(tblview, tblFields, tblExpression) as sCursor:
        for sRow in sCursor:
            with arcpy.da.UpdateCursor(featlyr, lyrFields, lyrExpression) as uCursor:
                for uRow in uCursor:
                    # Update the fields in the water meter feature to the values of the fields in the table record
                    uRow = sRow 
                    # Save the changes
                    uCursor.updateRow(uRow) 
else:
    # Bail if there are not the right number of records/features selected 
    # (e.g. there isn't a single record in the table and feature in the layer)
    arcpy.AddError("Not the right number of features/records selected, bailing!")
  • I agree that this works if the matched feature and row are the only records selected. I understood "highlighted" to be the yellow row that shows up when only selected records are being shown in a table view and the user clicks on the far left edge of a record. That kind of highlighted record is invisible to Python. However, if "highlighted" simply meant "selected" then this approach works since Python has no problem seeing normal record selections in a layer/table. – Richard Fairhurst May 19 '16 at 20:18
  • @RichardFairhurst I suppose that instead of using Select By Attribute + Highlight, I could go the route of Definition Query + Selection. Main thing i'm learning from this: I need to learn to write Python. – Nomkins May 19 '16 at 21:00
  • 1
    A Definition Query + Selection would work. This would only create a potential problem if you needed to add records that did not meet the requirements of the Definition Query, but it should work for all of your existing records. And yes, Python or ArcObjects custom code is required to do anything similar to the behavior you want, since there are no built in capabilities in ArcMap that resemble what you want. – Richard Fairhurst May 19 '16 at 21:30
  • I'm getting an error on line 16 with "if len(tblsel) == 1 and len(lyrsel) == 1:". It says that "Object type of NoneType has no len()". Any ideas? – Nomkins May 20 '16 at 14:02
  • Do you have something selected in your table and your layer? – Midavalo May 20 '16 at 19:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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