*UPDATE*
For samples of the correct code, see posts below.
I'll start off by apologizing for not having any sort of sample of my code, but I am really just unsure on how to begin the code, so all I have is notes of what I need.
I have a feature class that has a number of fields that are duplicated for 5 different customers. The fields that I need to focus on in this exercise are the Cust1Name, Cust1NodeID, Cust1HomeID, and 10 Cust1CircuitID fields. I'm using "Cust1", "Cust2", etc only as examples in place of their actual names...just stating that to eliminate your efforts in trying to add the customer number in a potential for/while loop. Essentially the fields look as they do below:
Cust1Name
Cust1NodeID
Cust1HomeID
Cust1CircuitID1
...
Cust1CirctuitID10
Cust2Name
Cust2NodeID
Cust2HomeID
Cust2CircuitID1
...
Cust2CircuitID10
etc...
My feature class has fields for all 5 customers, but not all 5 will be populated. I've used the Cust#NodeID field as my reference for whether calculations will run or not because that field determines if they are needed or not. Populated means run the calculation, while Null means do nothing.
if Cust1NodeID != None: return # insert calculation here else: return None
I also need to get a users input to know the amount of circuit ID's needed. The number varies from 1 to 10 circuit ID's.
numberIDs = arcpy.GetParameterAsText(0)
With this information I need the script to go through each Cust#NodeID field to check and see if it's null or not. If it's null, keep moving...if it has data, calculate the amount of circuit ID fields needed based on the input.
Again, sorry for having nothing to start with. I'm just confused on which route to take (for loop, while loop, if/if...), and I can't figure out any of them either way. I'm just not sure how to add so many arguments together.
*EDIT*
I'll also note that the circuit ID calculation itself is just a concatenation of the given fields, as shown below:
Cust1CircuitID1 = (Cust1Name) - (Cust1NodeID) - (Cust1HomeID) - (01)
Cust1CircuitID2 = (Cust1Name) - (Cust1NodeID) - (Cust1HomeID) - (02)
etc...
Solved! Go to Solution.
Until you've got more, it's hard to help. You almost certainly need to use a SearchCursor (to read) or UpdateCursor (to read/write) to loop through your records. Is that the missing piece?
Until you've got more, it's hard to help. You almost certainly need to use a SearchCursor (to read) or UpdateCursor (to read/write) to loop through your records. Is that the missing piece?
The UpdateCursor method works wonders, but I can't seem to get the string portion of the return calculation to work properly. It keeps returning a literal string. I tried single quotes, and I tried ' """ + var + "" ' both with an without the space in between, and I just kept getting a literal string.
import arcpy numIDs = arcpy.GetParameterAsText(0) # I equaled this to 1 in my testing to see if it would ignore CircuitID2 and it did fc = r'my node feature class' fields = ('Cust1NodeID', 'Cust1HomeID', 'Cust1Name', 'Cust1CircuitID1', 'Cust1CircuitID2', 'Cust1CircuitID3', 'Cust1CircuitID4', Cust1CircuitID5', 'Cust1CircuitID6', 'Cust1CircuitID7', 'Cust1CircuitID8', 'Cust1CircuitID9', 'Cust1CircuitID10') with arcpy.da.UpdateCursor(fc, fields) as cursor: for row in cursor: if row[0] != None: row[3] = "(" + Cust1Name + ") - (" + Cust1NodeID + ") - (" + Cust1HomeID + ") - (01)" elif (row[0] != None and numIDs >= 2): row[4] = "(" + Cust1Name + ") - (" + Cust1NodeID + ") - (" + Cust1HomeID + ") - (02)"
This runs through and only updates Cust1CircuitID1, but I just need to get over the whole literal string hand up. I only wrote it out to calculate the first two CircuitID fields, but as my script note above states, I set the variable to 1 so that it would only calculate the first one.
I've seen the UpdateCursor function in other code samples, and I've seen reference to it, but I haven't tried it yet. Glad your suggestion led me to do a little research and learn it a little better . I'll likely be going back and updating some other code that I've created using this method.
The values in the cursor are accessed according to their position in the fields list:
fields = ('Cust1NodeID', 'Cust1HomeID', 'Cust1Name', 'Cust1CircuitID1', 'Cust1CircuitID2', 'Cust1CircuitID3', 'Cust1CircuitID4', Cust1CircuitID5', 'Cust1CircuitID6', 'Cust1CircuitID7', 'Cust1CircuitID8', 'Cust1CircuitID9', 'Cust1CircuitID10')
...corresponds to indexed values:
row[0], row[1], row[2], ..., row[12]
So, to access the value in the Cust1Name position, you would use the value:
row[2]
... rather than Cust1Name.
or as Xander has suggested on a few occasions..before the
Cust1NodeID = row[0]
Cust1HomeID = row[1]
...
for row in rows:
then you can use their names
or you could also unwrap the args
Cust1NodeID, Cust1HomeID = row # or fields
but I haven't got a file to check
Yeah, I noticed how the row corresponded with each position in the variable list, but I didn't realize that I would use the actual "row" nomenclature for the variable in the concatenation. That did the trick!
Thanks once again, dkwiens! I'm very thankful for people like you and Dan_Patterson!
Does the code have the ability to step through each row and update them accordingly? In my example above the first line simply checks to see if the NodeID field is populated, and then if so it updates the CircuitID1 field. However, the second line checks whether the NodeID field is populated AND if the input variable is > or = to 2, and if so it updates the CircuitID2 field.
In the example above I used an input value of 1 just to see if it would stop there and not calculate the 2nd, and it seemed to work, but I believe it did for unwanted reasons. When I change the input variable to 2, the second line still doesn't calculate. If I remove the first line altogether and just run the second line, it populates the CircuitID2 field correctly.
Ideally the code should step through each if statement, check the parameters, and conditionally update the corresponding field below it, right?
if NodeID != None: calculate CircuitID1 elif NodeID != None and input variable >= 2: calculate CircuitID2 elif NodeID != None and input variable >= 3: calculate CircuitID3
etc...
So if I input 4, it'll update CircuitID1, 2, 3, and 4. However, if I only put 1, it'll update just CircuitID1. Is that not the way it should work?
The actual code that I used that doesn't update both the if and elif is below:
import arcpy numIDs = 2 fc = r'my node feature class' fields = ('NodeID', 'HomeID', 'CustName', 'CircuitID1', 'CircuitID2') with arcpy.da.UpdateCursor(fc, fields) as cursor: for row in cursor: if row[0] != None: row[3] = "(" + row[2] + ") - (" + row[0] + ") - (" + row[1] + ") - (01)" # this works fine elif row[0] != None and numIDs >= 2): row[4] = "(" + row[2] + ") - (" + row[0] + ") - (" + row[1] + ") - (02)" # this one won't run cursor.updateRow(row)
If I take the elif statement exactly as it is and put it in the if portion, it works, so I know the syntax is there for it to work, but something isn't allowing it to work in tandem with the other in an if/elif/elif/elif/elif format. When I run it just as it it typed above, it just runs through and updated the first if, and ignores the second. Any ideas why?
The if, elif, statement will only get past into the if section
if row[0] != None:
it will never see the elif section unless you provide a condition for the condition where numIDs < 2 ... like
if (row[0] != None) & (numIDs < 2):
do stuff
elif blah
blah
cursor.updateRow
However this logic is also flawed potentially. Do you want the cursor to be updated if row[0] is = None???
perhaps your logic should be
if (row[0] != None): if numIDs < 2: row[3] = "(" + row[2] + ") - (" + row[0] + ") - (" + row[1] + ") - (01)" # this works fine else row[4] = "(" + row[2] + ") - (" + row[0] + ") - (" + row[1] + ") - (02)" # this one won't run cursor.updateRow(row)
If row[0] has a null value, then I want the script to return nothing. Basically if there is no node name, then we don't need a circuit ID for that node.
I ran the following samples and got different errors with each:
for row in cursor: if (row[0] != None): if (numIDs == 1): row[3] = "(" + row[2] + ") - (" + row[0] + ") - (" + row[1] + ") - (01)" elif (numIDs == 2) row[3] = "(" + row[2] + ") - (" + row[0] + ") - (" + row[1] + ") - (01)" row[4] = "(" + row[2] + ") - (" + row[0] + ") - (" + row[1] + ") - (02)" cursor.updateRow(row)
This returns the error message:
"Parsing error SyntaxError: EOL while scanning string literal (line 16)"
for row in cursor: if (row[0] != None) & (numIDs < 2): row[3] = "(" + row[2] + ") - (" + row[0] + ") - (" + row[1] + ") - (01)" elif (row[0] != None) & (numIDs < 3): row[3] = "(" + row[2] + ") - (" + row[0] + ") - (" + row[1] + ") - (01)" row[4] = "(" + row[2] + ") - (" + row[0] + ") - (" + row[1] + ") - (02)" cursor.updateRow(row)
This returns the error message:
"Runtime error
Traceback (most recent call last):
File "<string>", line 16, in <module>
TypeError: coercing to Unicode: need string or buffer, NoneType found"