Kiểm tra qua ArcPy nếu ArcMap đang trong phiên chỉnh sửa?


11

Tôi đã tạo một nút bổ trợ Python giúp tăng tốc quy trình làm việc cho đồng nghiệp của mình bằng cách sao chép một thuộc tính lớp tính năng này sang thuộc tính khác. Nó sử dụng hàm arcpy.UpdateCthon để cập nhật một hàng trong lớp tính năng đích. Vì nó tồn tại bây giờ, tập lệnh nút này có thể được chạy bất kể chế độ chỉnh sửa. Rõ ràng khi nó chạy trong phiên chỉnh sửa, người dùng có thể chọn dừng chỉnh sửa và không lưu thay đổi, nhưng đây không phải là trường hợp khi tập lệnh chạy bên ngoài phiên chỉnh sửa.

Làm cách nào tôi có thể thêm một kiểm tra vào tập lệnh sẽ ngăn tập lệnh chạy nếu ArcMap hiện không có trong phiên chỉnh sửa?

Điều này liên quan đến ArcMap 10 & 10.1


Tôi cũng muốn kiểm tra với những người dùng ArcMap khác để xác minh rằng các bản cập nhật cho các bảng thường không được phép nếu không có trong phiên chỉnh sửa.

Vậy tập lệnh này chạy bên ngoài phiên chỉnh sửa như thế nào?

Kịch bản này cũng đưa ra một câu hỏi khác về thứ tự lựa chọn có vẻ ngẫu nhiên mà ArcMap thực hiện sẽ xảy ra với tôi khi tôi cập nhật bảng lớp tính năng thứ 2 từ danh sách, nhưng đó là cho một ngày khác.

Đây là tập lệnh như hiện tại (không có bất kỳ triển khai trình soạn thảo 10.1 nào):

Làm cách nào để thêm một kiểm tra để đảm bảo người dùng đang trong phiên chỉnh sửa?

def onClick(self):
    #Reference mxd
    mxd = arcpy.mapping.MapDocument("CURRENT")
    #Reference the main Data frame
    mm = arcpy.mapping.ListDataFrames(mxd, "MainMap")[0]
    #Reference the Water System Valve feature class
    waterValves = arcpy.mapping.ListLayers(mxd, "Water System Valve", mm)[0]
    #Reference the fire hydrant feature class
    fireHydrants = arcpy.mapping.ListLayers(mxd, "Water Hydrant", mm)[0]

    #Use the extent of the main DF to select all valves in the current view
    dfAsFeature = arcpy.Polygon(arcpy.Array([mm.extent.lowerLeft, mm.extent.lowerRight, mm.extent.upperRight, mm.extent.upperLeft]), mm.spatialReference)
    arcpy.SelectLayerByLocation_management(waterValves, "WITHIN", dfAsFeature,"", "NEW_SELECTION")

    arcpy.SelectLayerByAttribute_management(waterValves, "SUBSET_SELECTION", "LOCATIONID IS NULL")

    fields = ["LOCATIONID"]

    row, rows = None, None
    rows = arcpy.UpdateCursor(waterValves,fields)
    row = rows.next()
    valveList = []
    append = valveList.append

    #Loop through the valves table to update LocationID
    while row:
        builder = str(row.QSNO)+"-"+ str(row.VALVESEQNO)
        row.setValue("LOCATIONID", builder)
        append(builder)
        rows.updateRow(row)
        row = rows.next()

    del row, rows

    #New selection for fire hydrants
    arcpy.SelectLayerByLocation_management(fireHydrants, "WITHIN", dfAsFeature,"", "NEW_SELECTION")
    arcpy.SelectLayerByAttribute_management(fireHydrants, "SUBSET_SELECTION", "LOCATIONID IS NULL")

    row, rows = None, None
    rows = arcpy.UpdateCursor(fireHydrants,fields)
    row = rows.next()

    #Loop through fire hydrant table to update LocationID
    while row:
        for locID in valveList:
            construct = str(locID) + "-FH"
            #print construct
            row.setValue("LOCATIONID", construct)
            rows.updateRow(row)
            row = rows.next()

    del row, rows, valveList, mxd

Trình chỉnh sửa mô-đun truy cập dữ liệu dường như hoạt động độc lập với Trình chỉnh sửa tiêu chuẩn. Tôi sẽ hoan nghênh mọi ý tưởng bổ sung về thử nghiệm cho phiên chỉnh sửa hoạt động. -Karl
KarlJr

Bạn có thể cung cấp thêm một chút thông tin? Điều gì dẫn bạn đến kết luận này cho những người trong chúng ta chưa khám phá mô-đun?
Jay Laura

Câu trả lời:


6

Đây là một chức năng chung dựa trên bài viết này.

Có thể đây là một chút ít hơn so với giải pháp ArcObjects, nhưng nó chắc chắn có vẻ như ít rắc rối hơn! Đơn giản là tốt hơn phức tạp. Ngoại trừ khi nó không.

Ví dụ sử dụng:

if CheckEditSession(tbl):
    print("An edit session is currently open.")

mã:

def CheckEditSession(lyr):
    """Check for an active edit session on an fc or table.
    Return True of edit session active, else False"""
    edit_session = True
    row1 = None
    try:
        # attempt to open two cursors on the input
        # this generates a RuntimeError if no edit session is active
        OID = arcpy.Describe(lyr).OIDFieldName
        with arcpy.da.UpdateCursor(lyr, OID) as rows:
            row = next(rows)
            with arcpy.da.UpdateCursor(lyr, OID) as rows2:
                row2 = next(rows2)
    except RuntimeError as e:
        if e.message == "workspace already in transaction mode":
            # this error means that no edit session is active
            edit_session = False
        else:
            # we have some other error going on, report it
            raise
    return edit_session

+1 Khái niệm hay, tuy nhiên OP muốn dừng lại nếu không tham gia phiên chỉnh sửa và tiếp tục nếu đó là phiên chỉnh sửa. Câu trả lời của bạn dường như làm ngược lại. Có thể sẽ không mất nhiều thời gian để xoay chuyển điều đó.
Midavalo

OP đã giải quyết vấn đề của mình rồi, bài đăng này chỉ là đóng băng với chức năng thường hữu ích hơn. Tôi đã sửa đổi ví dụ của mình để rõ ràng hơn về cách sử dụng chức năng.
Giá của Curtis

4

Giải pháp của tôi cho vấn đề này là sử dụng các tiện ích mở rộng có sẵn cho Thanh công cụ Arcpy Addin. Tôi đã thêm một tiện ích mở rộng để nghe phiên chỉnh sửa bắt đầu hoặc kết thúc. Tôi có tất cả các nút của mình trên thanh được đặt thành: self.enable = false "để bắt đầu và sau đó các nút này được bật hoặc tắt bằng cách bắt đầu hoặc dừng phiên chỉnh sửa.

class Active_Edit_Session(object):
"""Implementation for NEZ_EDITS_addin.Listen_for_Edit_Session (Extension)"""
def __init__(self):
    self.enabled = True
def onStartEditing(self):
    button_3100.enabled=True    
def onStopEditing(self, save_changes):
    button_3100.enabled=False

class LFM_3100(object):
    """Implementation for LFM_3100.button_3100 (Button)"""
    def __init__(self):
        self.enabled = False
        self.checked = False
    def onClick(self):
        ......

Đây có vẻ là một giải pháp đáng để thử. Cảm ơn bạn
user18412

4

Tôi đang đăng một câu trả lời khác vì tôi đã học được một phương pháp mới để kiểm tra trạng thái của Trình chỉnh sửa trong ArcMap bằng ArcObjects và Python cùng nhau. Câu trả lời của tôi mượn rất nhiều từ công việc được thực hiện bởi Mark Cederholm như được tham chiếu trong bài đăng này: Làm cách nào để tôi truy cập ArcObjects từ Python? và các ví dụ mã do Matt Wilkie cung cấp trong tệp "Snippits.py" của mình. Bạn sẽ cần phải làm theo các hướng dẫn được cung cấp trong câu trả lời đầu tiên để tải xuống và cài đặt comtypes và sau đó lấy bản sao của tập lệnh Snippets.py. Tôi đang đăng một bản sao của các chức năng thiết yếu từ kịch bản dưới đây.

Khi hàm ArcMap_GetEditSessionStatus () được gọi, nó sẽ kiểm tra trạng thái hiện tại của Trình chỉnh sửa trong ArcMap và trả về đúng hoặc sai. Điều này cho phép tôi kiểm tra xem người dùng đã sẵn sàng sử dụng công cụ của tôi hay họ cần được nhắc để bắt đầu phiên chỉnh sửa. Nhược điểm của phương pháp này là yêu cầu cài đặt comtypes trước khi ArcObjects có thể được sử dụng trong Python, vì vậy việc chia sẻ một công cụ yêu cầu gói này trong môi trường văn phòng nhiều người dùng là không thể. Với kinh nghiệm hạn chế của mình, tôi không chắc chắn làm thế nào để kết hợp tất cả lại với nhau để chia sẻ dễ dàng như một bổ trợ công cụ Esri Python. Đề xuất làm thế nào để làm điều này sẽ được đánh giá cao.

#From the Snippits.py file created by Matt Wilkie
def NewObj(MyClass, MyInterface):
    """Creates a new comtypes POINTER object where\n\
    MyClass is the class to be instantiated,\n\
    MyInterface is the interface to be assigned"""
    from comtypes.client import CreateObject
    try:
        ptr = CreateObject(MyClass, interface=MyInterface)
        return ptr
    except:
        return None

def CType(obj, interface):
    """Casts obj to interface and returns comtypes POINTER or None"""
    try:
        newobj = obj.QueryInterface(interface)
        return newobj
    except:
        return None

def CLSID(MyClass):
    """Return CLSID of MyClass as string"""
    return str(MyClass._reg_clsid_)

def GetApp(app="ArcMap"):
    """app must be 'ArcMap' (default) or 'ArcCatalog'\n\
    Execute GetDesktopModules() first"""
    if not (app == "ArcMap" or app == "ArcCatalog"):
        print "app must be 'ArcMap' or 'ArcCatalog'"
        return None
    import comtypes.gen.esriFramework as esriFramework
    import comtypes.gen.esriArcMapUI as esriArcMapUI
    import comtypes.gen.esriCatalogUI as esriCatalogUI
    pAppROT = NewObj(esriFramework.AppROT, esriFramework.IAppROT)
    iCount = pAppROT.Count
    if iCount == 0:
        return None
    for i in range(iCount):
        pApp = pAppROT.Item(i)
        if app == "ArcCatalog":
            if CType(pApp, esriCatalogUI.IGxApplication):
                return pApp
            continue
        if CType(pApp, esriArcMapUI.IMxApplication):
            return pApp
    return None


def GetModule(sModuleName):
    """Import ArcGIS module"""
    from comtypes.client import GetModule
    sLibPath = GetLibPath()
    GetModule(sLibPath + sModuleName)


def GetDesktopModules():
    """Import basic ArcGIS Desktop libraries"""
    GetModule("esriFramework.olb")
    GetModule("esriArcMapUI.olb")

#My added function for checking edit session status
def ArcMap_GetEditSessionStatus():

    GetDesktopModules()
    GetModule("esriEditor.olb")
    import comtypes.gen.esriSystem as esriSystem
    import comtypes.gen.esriEditor as esriEditor
    pApp = GetApp()
    pID = NewObj(esriSystem.UID, esriSystem.IUID)
    pID.Value = CLSID(esriEditor.Editor)
    pExt = pApp.FindExtensionByCLSID(pID)
    pEditor = CType(pExt, esriEditor.IEditor)
    if pEditor.EditState == esriEditor.esriStateEditing:
        print "Edit session active"
        return True
    else:
        print "Not in an edit session"
        return False

1
Điều này làm việc tuyệt vời. Tôi biết đây là một bài viết cũ, nhưng nếu bạn muốn gói nó lên để nó dễ mang theo hơn, bạn có thể tạo mô-đun đoạn trích dưới dạng gói python và bao gồm các comtypes trong đó. Tôi làm điều này cho công ty của mình và tôi đã đặt tất cả các mô-đun Python tùy chỉnh của chúng tôi lên mạng chia sẻ. Mỗi khi ai đó cài đặt / cài đặt lại phần mềm ArcGIS, tôi sẽ cho họ chạy một tệp bó sửa đổi Desktop.pthtệp của họ để bao gồm đường dẫn đầy đủ đến chia sẻ mạng, vì vậy mọi người có thể tự động nhập mọi thứ.
crmackey

2

Làm thế nào về việc sử dụng các mô-đun truy cập dữ liệu ? Có vẻ như bạn có thể bắt đầu một phiên chỉnh sửa với mô-đun này.

Một vài cảnh báo:

  1. Tôi chưa thử mô-đun này và tôi không chắc nó có tương thích 10.0 không. (Mới trong 10.1?)
  2. Ví dụ 1 cho thấy việc sử dụng một withtuyên bố. Đây là một mô hình tuyệt vời để thực hiện vì nó xử lý tốt các ngoại lệ tiềm năng.
  3. Bạn có thể kiểm tra xem phiên chỉnh sửa đã hoạt động chưa bằng cách thử khởi chạy một phiên trong một try / excepttuyên bố.

Tôi thực sự bắt đầu với việc sử dụng lớp Editor trong mô-đun truy cập dữ liệu khi tôi bắt đầu dự án này nhưng việc sử dụng nó dường như không thành vấn đề. Bao gồm "với arcpy.da.Editor (không gian làm việc) là chỉnh sửa:" trong tập lệnh của tôi không kích hoạt trình chỉnh sửa và thử stopOperation / stop. Chỉnh sửa không dừng trình chỉnh sửa. Nhưng tôi có thể làm sai ...
user18412

1

Vì vậy, đây là cách tôi khắc phục vấn đề không thể kiểm soát nếu ai đó sử dụng công cụ của tôi có trong phiên chỉnh sửa hay không:

#Reference to mxd and layers script here. Then...
try:
    fields = ("OBJECTID")
    upCursor = arcpy.da.UpdateCursor(waterValves, fields)
    with upCursor as cursor:
        for row in cursor:
            pass
except:
    pythonaddins.MessageBox('You are not in an edit session', 'Warning', 0)

else:
#Rest of script

Kịch bản hoạt động vì nó cố gắng tạo UpdateCthon trên một lớp có một UpdateCoder khác sau đó trong tập lệnh. Điều này vi phạm hành vi của mô-đun truy cập dữ liệu. Theo trang Tài nguyên ESRI trên arcpy.da.UpdateCoder:

"Việc mở các thao tác chèn và / hoặc cập nhật đồng thời trên cùng một không gian làm việc bằng các con trỏ khác nhau đòi hỏi phải bắt đầu một phiên chỉnh sửa."

Tôi không hài lòng với giải pháp này vì nó là một bản hack nhiều hơn những gì tôi tưởng tượng là kịch bản phù hợp. Ai có ý tưởng tốt hơn?


1
Đây chỉ là một ý tưởng nhưng bạn có thể thử truy cập vào đối tượng Editor trong ArcObjects và kiểm tra thuộc tính EditState của nó dường như là thứ còn thiếu từ arcpy? Tôi chưa bao giờ thử thao tác ArcObjects từ python nhưng chủ đề này nói về cách làm điều đó?
Hornbydd
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.