|
POST
|
I tried your code without issue. An error at line 10 would suggest that either existingFC was not found or myfields contains a field name that is not in existingFC. In either case the message would be: RuntimeError: FieldMap: Error in adding input field to field map You could add a section to read the fields in your feature, and if they are in your field list, then add them to the field map.
... View more
11-25-2019
08:22 PM
|
0
|
0
|
5677
|
|
POST
|
Try the following for the tool validator: import arcpy
class ToolValidator(object):
def __init__(self):
self.params = arcpy.GetParameterInfo()
def initializeParameters(self):
return
def updateParameters(self):
if self.params[0].value == None:
self.params[0].value = "Digital Map"
if self.params[0].valueAsText == "Digital Map":
self.params[1].filter.list = ["No scale required"]
else:
self.params[1].filter.list = ["1:10,000", "1:25,000"]
if self.params[1].value not in self.params[1].filter.list:
self.params[1].value = self.params[1].filter.list[0]
return
def updateMessages(self):
return For testing, I used Desktop 10.5. I set the script tool parameters as type string, and populated the map type filter with the digital or paper map options. I did not set the filter list for the map scale. I find it a little easier to use a Python toolbox. You don't have to go to the properties dialog box to edit a tool validator; everything fits into one script. My test version: import arcpy
class Toolbox(object):
def __init__(self):
self.label = "Toolbox"
self.alias = ""
self.tools = [Tool]
class Tool(object):
def __init__(self):
self.label = "Tool"
self.description = ""
self.canRunInBackground = False
def getParameterInfo(self):
MapType = arcpy.Parameter(
displayName="Map Type",
name="MapType",
datatype="String",
parameterType="Required",
direction="Input")
MapType.filter.list = ["Digital Map", "Paper Map"]
MapType.value = "Digital Map"
MapScale = arcpy.Parameter(
displayName="Map Scale",
name="MapScale",
datatype="String",
parameterType="Required",
direction="Input")
MapScale.filter.list = ["No scale required"]
MapScale.value = "No scale required"
params = [MapType, MapScale]
return params
def isLicensed(self):
return True
def updateParameters(self, parameters):
"""Modify the values and properties of parameters before internal
validation is performed. This method is called whenever a parameter
has been changed."""
if parameters[0].valueAsText == "Digital Map":
parameters[1].filter.list = ["No scale required"]
else:
parameters[1].filter.list = ["1:10,000", "1:25,000"]
if parameters[1].value not in parameters[1].filter.list:
parameters[1].value = parameters[1].filter.list[0]
return
def updateMessages(self, parameters):
return
def execute(self, parameters, messages):
"""The source code of the tool."""
return Hope this helps.
... View more
11-24-2019
08:28 PM
|
1
|
0
|
2457
|
|
POST
|
Working with script tools and Python toolboxes can be frustrating. The .altered property looks like it is always True if the parameter has a value, and False if it is None. The .hasBeenValidated property can be switched to False just by clicking on a drop-down without changing the selected value. Using global variables can also be tricky. If I understand what you are trying to accomplish ( select a feature/table, a field in that table, and populate a drop-down with the field's attributes and allow a user to add to the list ), here are a couple of ideas using a Python toolbox ( with a .pyt extension ). One idea is to use some global variables to keep track of parameter value changes. The second is to allow the user typed data to be inserted at the top of the drop-down temporarily allowing the value to be used. import arcpy
import pythonaddins
class Toolbox(object):
def __init__(self):
"""Define the toolbox (the name of the toolbox is the name of the
.pyt file)."""
self.label = "Select Value"
self.alias = "selection"
self.tools = [Tool]
class Tool(object):
def __init__(self):
"""Define the tool (tool name is the name of the class)."""
self.label = "Tool"
self.description = "Select field and attribute from feature"
self.canRunInBackground = False
def getParameterInfo(self):
# create global variables here as
# getParameterInfo is only called once
global fcValue # keep track of parameter changes
fcValue = None # inFeature
global fldValue
fldValue = None # field1
global attrValue
attrValue = None # attribute1
global attrList
attrList = None # attribute list
'''
# for debugging, display values in an annoying pop-up box
pythonaddins.MessageBox('fcValue: {}\nfldValue: {}\nattrValue: {}\nattrList: {}\nstatus: {}'.format(
fcValue,
fldValue,
attrValue,
attrList,
'initialized'
),'Get Parameters')
'''
# First parameter
inFeature = arcpy.Parameter(
displayName="Input Features",
name="inFeature",
datatype=["DEFeatureClass","GPFeatureLayer"],
parameterType="Required",
direction="Input")
# Second parameter
field1 = arcpy.Parameter(
displayName="Field 1",
name="field1",
datatype="Field",
parameterType="Required",
direction="Input")
field1.parameterDependencies = [inFeature.name]
field1.filter.list = ["Short", "Long", "Double", "Float", "Text"]
# Third parameter
attribute1 = arcpy.Parameter(
displayName="Value 1",
name="attribute1",
datatype="String",
parameterType="Required",
direction="Input")
attribute1.parameterDependencies = [inFeature.name, field1.name]
# Fourth parameter
field2 = arcpy.Parameter(
displayName="Field 2",
name="field2",
datatype="Field",
parameterType="Required",
direction="Input")
field2.parameterDependencies = [inFeature.name]
field2.filter.list = ["Short", "Long", "Double", "Float", "Text"]
# Fifth parameter
attribute2 = arcpy.Parameter(
displayName="Value 2",
name="attribute2",
datatype="String",
parameterType="Required",
direction="Input")
attribute2.parameterDependencies = [inFeature.name, field1.name]
params = [inFeature, field1, attribute1, field2, attribute2]
return params
def isLicensed(self):
"""Set whether tool is licensed to execute."""
return True
def updateParameters(self, parameters):
# globals are initalized in getParameterInfo to keep track of parameter changes
global fcValue
global fldValue
global attrValue
global attrList
'''
# for debugging, display annoying popup box everytime updateParameters is called to show parameter values
# popup box is not always on top, so you may need to move some windows
pythonaddins.MessageBox('0: {}\n1: {}\n2: {}\n3: {}\n4: {}'.format(
parameters[0].value,
parameters[1].value,
parameters[2].value,
parameters[3].value,
parameters[4].value
),'Update Parameters (in)')
'''
# this section uses globals to track changes in the parameters
if parameters[0].value and not parameters[1].value:
fcValue = parameters[0].value # save value to global
if parameters[0].value and parameters[1].value: # get first field and value list
fc, col = parameters[0].valueAsText, parameters[1].valueAsText
desc = arcpy.Describe(parameters[0])
if desc.dataType == 'FeatureLayer': # if feature layer, use catalog path
fc = desc.catalogPath
if parameters[0].valueAsText != fcValue or parameters[1].valueAsText != fldValue: # feature or field has changed
fcValue = parameters[0].valueAsText # save value to global
fldValue = parameters[1].valueAsText
# get the field's attributes
attrList = [str(val) for val in sorted(set(row[0] for row in arcpy.da.SearchCursor(fc,col)))]
parameters[2].filter.list = attrList # save attribute list to global
if parameters[2].value is None: # default to first item in list
parameters[2].value = parameters[2].filter.list[0]
else:
if parameters[2].valueAsText != attrValue: # attribute selection changed
if parameters[2].value not in attrList:
attrList.insert(0,parameters[2].value)
attrList = sorted(attrList)
parameters[2].filter.list = attrList
attrValue = parameters[2].valueAsText # save selected value to global
# this section only allows 1 change to be added to top of attribute list temporarly
if parameters[0].value and parameters[3].value: # get second field and value list
fc, col = parameters[0].valueAsText, parameters[3].valueAsText
desc = arcpy.Describe(parameters[0])
if desc.dataType == 'FeatureLayer': # if feature layer, use catalog path
fc = desc.catalogPath
filter2 = [str(val) for val in sorted(set(row[0] for row in arcpy.da.SearchCursor(fc,col)))]
if parameters[4].value is None:
parameters[4].filter.list = filter2 # default to first item in list
parameters[4].value = parameters[4].filter.list[0]
else:
if parameters[4].value not in filter2:
filter2.insert(0,parameters[4].value)
parameters[4].filter.list = filter2
'''
# for debugging, display annoying popup box everytime updateParameters is called
pythonaddins.MessageBox('0: {}\n1: {}\n2: {}\n3: {}\n4: {}'.format(
parameters[0].value,
parameters[1].value,
parameters[2].value,
parameters[3].value,
parameters[4].value
),'Update Parameters (out)')
'''
return
def updateMessages(self, parameters):
"""Modify the messages created by internal validation for each tool
parameter. This method is called after internal validation."""
return
def execute(self, parameters, messages):
"""The source code of the tool."""
inFeature = parameters[0].valueAsText
field1 = parameters[1].valueAsText
attribute1 = parameters[2].valueAsText
field2 = parameters[3].valueAsText
attribute2 = parameters[4].valueAsText
messages.addMessage(
"\nInput Feature: {}".format(inFeature))
messages.addMessage(
"\nSelected Field: {}".format(field1))
messages.addMessage(
"\nField Property: {}".format(attribute1))
messages.addMessage(
"\nSelected Field: {}".format(field2))
messages.addMessage(
"\nField Property: {}".format(attribute2))
desc = arcpy.Describe(parameters[0])
messages.addMessage(
"\nDataType: {}\nPath: {}".format(desc.dataType, desc.catalogPath))
return I use pythonaddins.MessageBox() to display some annoying pop-up message boxes that can show the parameter values at various times. Global variables seem to work if they are declared in the getParameterInfo() section. They can then be used in the updateParameters() validation section. My testing was with Desktop 10.5. Hopefully, this will give you some ideas.
... View more
11-24-2019
06:45 PM
|
0
|
0
|
1975
|
|
POST
|
I'm wondering if you installed a second version of Python when you installed pythonwin. Its been some time, but I seem to recall a prompt from pythonwin at install time asking about using existing Python or a new install. From your traceback image above, I see the path 'C:\Python27\Lib\site-packages\pythonwin.....' which I don't think should be. In your pythonwin Interactive Window, try the following and share the printout: >>> import sys
>>> sys.path
['C:\\', 'C:\\Windows\\system32\\python27.zip', 'C:\\Python27\\ArcGIS10.6\\DLLs', 'C:\\Python27\\ArcGIS10.6\\lib', 'C:\\Python27\\ArcGIS10.6\\lib\\plat-win', 'C:\\Python27\\ArcGIS10.6\\lib\\lib-tk', 'C:\\Python27\\ArcGIS10.6\\Lib\\site-packages\\Pythonwin', 'C:\\Python27\\ArcGIS10.6', 'C:\\Python27\\ArcGIS10.6\\lib\\site-packages', 'C:\\Program Files (x86)\\ArcGIS\\Desktop10.6\\bin', 'C:\\Program Files (x86)\\ArcGIS\\Desktop10.6\\ArcPy', 'C:\\Program Files (x86)\\ArcGIS\\Desktop10.6\\ArcToolBox\\Scripts', 'C:\\Python27\\ArcGIS10.6\\lib\\site-packages\\win32', 'C:\\Python27\\ArcGIS10.6\\lib\\site-packages\\win32\\lib']
>>> sys.executable
'C:\\Python27\\ArcGIS10.6\\Lib\\site-packages\\Pythonwin\\Pythonwin.exe'
>>> import os
>>> os.listdir(r'C:\Python27')
['ArcGIS10.6']
>>> os.listdir(r'C:\Python27\ArcGIS10.6')
['DLLs', 'Doc', 'include', 'Lib', 'libs', 'LICENSE.txt', 'NEWS.txt', 'python.exe', 'pythonw.exe', 'pywin32-wininst.log', 'README.txt', 'Removepywin32.exe', 'Scripts', 'tcl', 'Tools', 'w9xpopen.exe']
# I've included my output above as a sample of what you might see.
# The specific python commands to enter, in order, are:
import sys
sys.path
sys.executable
import os
os.listdir(r'C:\Python27')
os.listdir(r'C:\Python27\ArcGIS10.6')
... View more
11-22-2019
02:07 PM
|
0
|
0
|
1752
|
|
POST
|
Here's an additional script example using the sqlite3 module to work with the realdate and unixepoch formats. SQLite functions can convert a date/time to local date/time without the datetime module; see lines 17 and 33 below. import sqlite3
con = sqlite3.connect(":memory:")
# sqlite function datetime(timestring, modifier, ...)
# timestring in one of several formats including 'YYYY-MM-DD HH:MM:SS'
# modifier 'localtime' assumes timestring is in UTC and displays local time
# see: https://sqlite.org/lang_datefunc.html
print 'realdate format'
query = "select julianday('now')" # output realdate format
jd = list(con.execute(query))[0][0]
print jd # 2458798.48683
query = "select date({0}) || ' ' || time({0})".format(jd) # utc time
dt = list(con.execute(query))[0][0]
print dt # 2019-11-10 23:41:02
query = "select datetime(date({0}) || ' ' || time({0}),'localtime')".format(jd) # local time
dt = list(con.execute(query))[0][0]
print dt # 2019-11-10 14:41:02
print
query = "select julianday('2019-11-07 11:13:30-09:00')" # output realdate format
jd = list(con.execute(query))[0][0]
print jd # 2458795.34271
print
print 'unixepoch formt'
query = "SELECT (julianday('now') - 2440587.5)*86400.0" # output uxixepoch
ue = list(con.execute(query))[0][0]
print ue # 1573429262.01
query = "select datetime({0},'unixepoch')".format(ue)
dt = list(con.execute(query))[0][0]
print dt # 2019-11-10 23:41:02
query = "select datetime({0},'unixepoch','localtime')".format(ue)
dt = list(con.execute(query))[0][0]
print dt # 2019-11-10 14:41:02
print
... View more
11-10-2019
04:22 PM
|
0
|
0
|
2943
|
|
POST
|
SQLite can store dates as text, real or integer. When you create a replica SQLite geodatabase, the date/time format is real. It counts days from November 4714 BC. You can use sqlite3 to query the database and convert the dates: import sqlite3 as lite
from datetime import datetime
from dateutil import tz
import time, re
gdb = r'C:\path\to\date_time_test.geodatabase'
field = 'EditDate'
table = 'Date_Time_Test'
query = "SELECT {0}, date({0}), time({0}) FROM {1}".format(field, table)
# print query
con = lite.connect(gdb)
with con:
cur = con.cursor()
cur.execute(query)
rows = cur.fetchall()
print "{}\t{}".format('EditDate','DateTime')
for row in rows:
dt = "{} {}".format(row[1],row[2])
lt = datetime.strptime(dt, '%Y-%m-%d %H:%M:%S').replace(tzinfo=tz.gettz('UTC')).astimezone(tz.tzlocal())
ts = time.strftime('%Y-%m-%d %H:%M:%S %Z', time.localtime(time.mktime(lt.timetuple())))
print "{}\t{}".format(row[0], ts[:21]+re.sub('[^A-Z]','',ts[21:]))
# ======================
print # another test example
EditDate = 2458795.34270833 # submitted a record at 11:13 AM (on Nov 7, 2019) Alaska Standard Time
print "EditDate: {}".format(EditDate)
con = lite.connect(":memory:")
dt = list(con.execute("select date("+str(EditDate)+") || ' ' || time("+str(EditDate)+")"))[0][0]
lt = datetime.strptime(dt, '%Y-%m-%d %H:%M:%S').replace(tzinfo=tz.gettz('UTC')).astimezone(tz.tzlocal())
ts = time.strftime('%Y-%m-%d %H:%M:%S %Z', time.localtime(time.mktime(lt.timetuple())))
print ts[:21]+re.sub('[^A-Z]','',ts[21:]) The second part of the script will convert an EditDate date of 2458795.34271 to the string 2019-11-07 11:13:30 AST. This is from your first question. For more information: SQLite Date and Time Functions Tutorial: SQLite Date and Time Calculating julian date in python
... View more
11-09-2019
12:38 PM
|
1
|
0
|
2943
|
|
POST
|
Here's one possibility: import arcpy
import csv
fc = r'C:\Path\to\file.gdb\feature'
# field names into list (you could use arcpy.Describe to get/select field names)
fields = ['Field1','Field2','FieldN'] # list of field names
sheetname = 'csv_test'
with open('{}.csv'.format(sheetname), 'wb') as outf:
dw = csv.DictWriter(
outf,
quotechar='"',
fieldnames=fields
)
dw.writeheader()
with arcpy.da.SearchCursor(fc, fields) as rows:
for row in rows:
dw.writerow(dict(zip(fields, row)))
print "File written: {}".format(sheetname) You can use Describe to get information on the feature's fields and use that information to create your field list. If you build a tool using the code above, you could allow the user to select fields. You could also modify the DictWriter to output a tab delimited file.
... View more
11-05-2019
09:48 AM
|
3
|
1
|
16667
|
|
POST
|
Done that too. I try to remember longitude/latitude (reverse alpha, but matching x/y). Doesn't help when Google Maps and others use latitude/longitude or y/x.
... View more
11-01-2019
12:40 PM
|
0
|
0
|
2881
|
|
POST
|
Make sure you are testing with the right longitude/latitude. import arcpy
wgs84 = arcpy.SpatialReference(4326) # GCS_WGS_1984
utm = arcpy.SpatialReference(26912) # NAD_1983_UTM_Zone_12N
lon = 10.0
lat = 10.0
utm_point = arcpy.PointGeometry(arcpy.Point(lon,lat), wgs84).projectAs(utm)
print utm_point.JSON
# {"x":"NaN","y":"NaN","spatialReference":{"wkid":26912,"latestWkid":26912}}
lon = -66.0
lat = -90.0
utm_point = arcpy.PointGeometry(arcpy.Point(lon,lat), wgs84).projectAs(utm)
print utm_point.JSON
# {"x":500000.90467679536,"y":-9997964.038261544,"spatialReference":{"wkid":26912,"latestWkid":26912}}
lon = -90.1994
lat = 38.6270 # St Louis
utm_point = arcpy.PointGeometry(arcpy.Point(lon,lat), wgs84).projectAs(utm)
print utm_point.JSON
# {"x":2318817.8976651346,"y":4486685.917933098,"spatialReference":{"wkid":26912,"latestWkid":26912}}
It appears that your longitude needs to be -66.0 or to the west with the desired spatial reference system.
... View more
11-01-2019
10:23 AM
|
1
|
2
|
2881
|
|
POST
|
Each row in the update cursor contain a list of the field values returned. In this case: the field list: ['FACILITY_ID', 'SHAPE@X', 'SHAPE@Y']
row[0] = FACILITY_ID
row[1] = SHAPE@X
row[2] = SHAPE@Y So changing the value of row[0] would cause the facility ID to be updated. I suppose in reality all the fields in the row are actually updated, it is just that unless the value has been changed, the update would not be noticeable. Instead of using indexing (ie. row[0]), you can use Joshua Bixby's approach to read the cursor into specific named variables. This might be an easier way to keep things organized. See the last three lines in Joshua's code. In line 4 of his code, change the SearchCursor to an UpdateCursor (I think this was just a typo). Hope this helps.
... View more
10-10-2019
11:30 AM
|
2
|
8
|
2633
|
|
POST
|
You don't need both a SearchCursor and an UpdateCursror. Just use the UpdateCursor: with arcpy.da.UpdateCursor(fc,['FACILITY_ID', 'SHAPE@X', 'SHAPE@Y'],'''FACILITY_ID IS NULL''') as cursor:
for row in cursor:
x = str(abs(int(row[1])))[:4]
y = str(abs(int(row[2])))[:4]
row[0] = x + y # concatenate strings x and y
cursor.updateRow(row) If you really want to use the x and y coordinates to create a facility ID, you may wish to format the x/y in such a way to consistently get your number. These values will be a type float, with a decimal somewhere. It may also be a negative number. So both a minus sign and a decimal may appear in your concatenation string. I converted these values to a positive integer before taking the right 4 digits. It should also be noted that the facility ID may not be unique, and it is a string so the facility ID should be type text.
... View more
10-10-2019
09:49 AM
|
2
|
12
|
2633
|
|
POST
|
Here's my latest test. It looks for a pattern of TX or TAX and selects everything until a letter is found that is neither TX nor TAX. The test code: import re
recs = [
"12-5N-5W SW NW SW S & W OF CANAL,, TX 2 IN SWNW LS TX 2-A",
"23-3N-2W SW 4TH ST TOWNHOMES TX 11271 IN LT 4C BLK 1",
"07-4N-3W NE NENE S&W OF HWY",
"04-5N-5W SE TAX 3 & TAX 4 IN NWSE",
"22-3N-2W SE NAMPA ORIGINAL TX 98728 OF LT 32 BLK 34",
"02-3N-2W NW TX 03475 LS RD IN S 1/2 NW12",
"21-4N-3W SW TX 86, 89, 90 & 93 IN S 1/2 OF SW"
]
pattern = re.compile(r"((?:TX|TAX) [^A-Z]+ )")
for rec in recs:
print ''.join((pattern.findall(rec))).strip()
# outputs:
TX 2
TX 11271
(blank line)
TAX 3 & TAX 4
TX 98728
TX 03475
TX 86, 89, 90 & 93 So I would suggest trying something like: import arcpy
import re
pattern = re.compile(r"((?:TX|TAX) [^A-Z]+ )")
fc = r'C:\Temp\Descriptions.shp'
with arcpy.da.UpdateCursor(fc,['Legal','Legal2']) as cursor:
for row in cursor:
row[1] = ''.join(pattern.findall(row[0].upper())).strip()
cursor.updateRow(row) Hope this helps.
... View more
10-01-2019
11:12 AM
|
2
|
7
|
4858
|
|
POST
|
To clarify, you want to start with either "TX" or "TAX" and stop just before "IN"?
... View more
09-30-2019
09:11 AM
|
0
|
9
|
4858
|
|
POST
|
I haven't worked with polygons containing holes. From a quick search of Geonet and the web, I didn't find a solution for buffering a polygon with holes as you wish to do. I'm not sure how the intersect tool would deal with holes; perhaps it could remove portions of the lines where the hole is located (but it wouldn't include a buffer). Since this is an old question marked answered, I suggest you pose a new question with a link to this one.
... View more
09-26-2019
12:07 PM
|
0
|
0
|
679
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 10-27-2016 02:23 PM | |
| 1 | 09-09-2017 08:27 PM | |
| 2 | 08-20-2020 06:15 PM | |
| 1 | 10-21-2021 09:15 PM | |
| 1 | 07-19-2018 12:33 PM |
| Online Status |
Offline
|
| Date Last Visited |
02-12-2026
07:13 PM
|