Thay đổi hàng loạt lớp tính năng và bí danh trường bằng ArcPy?


14

Tôi có hơn một trăm FC, mỗi FC có 10 hoặc 20 thuộc tính để thêm hoặc thay đổi bí danh cho, hai hoặc nhiều lần trong một năm. Không cần phải nói, đây không phải là điều tôi sẽ lẩm bẩm. Làm thế nào tôi có thể tự động hóa quá trình này?

Giải pháp Python ưa thích nhưng sẽ sử dụng bất cứ thứ gì hoạt động.

Tôi có quyền truy cập Arcgis 9.3.1 và 10 (cấp giấy phép ArcInfo).


1
Tôi tìm thấy [Chỉnh sửa lược đồ lớp tính năng] [1] mẫu nhà phát triển v9.3 cho ArcCatalog. Nó thay đổi bí danh cho các lớp đối tượng được chọn thành giá trị được mã hóa cứng trong tập lệnh. Vì vậy, không phải là một quá trình hàng loạt mà đi theo hướng đó. [1]: resource.esri.com/help/9.3/ArcGISDesktop/com/samples/
mẹo

có liên quan (một khối xây dựng nền tảng): gis.stackexchange.com/questions/80/NH
matt wilkie

Câu trả lời:


7

Kể từ phiên bản 10.1 AlterAliasName () có thể được sử dụng để đặt lại các bảng bí danh:

table = r"C:\path\to\connection.sde\OWNER.TABLE"
arcpy.AlterAliasName(table, "table_alias")

Kể từ phiên bản 10.3 Alter Field có thể được sử dụng để đặt lại các trường bí danh:

table = r"C:\path\to\connection.sde\OWNER.TABLE"
arcpy.AlterField_management(table, "FIELD_NAME", new_field_alias="field_alias")

8

Với sự giúp đỡ từ Mark Cederholm, tôi có một giải pháp làm việc bằng cách sử dụng python và arcobjects . Đó là xung quanh các cạnh, nhưng nó đã hoàn thành công việc. Sau khi làm theo công thức trên trang đó, hãy tạo một tập lệnh mới sử dụng các GetLibPath, NewObj, CType, OpenFeatureClasshàm từ đó snippets.py. Đồng thời tạo các bảng tra cứu đổi tên ở định dạng .csv:

Tra cứu bí danh từ trường đến trường (att_code-name_lookup.csv):

Attrib_Name,Alias_Name
CODE,Specification Code
VALDATE,Validity Date
...

Lớp tính năng để tra cứu bí danh FC (fc_code-name_lookup.csv):

"FC_Name","AliasName"
"BS_1250009_0","Navigational Aid"
"BS_1370009_2","Residential Area"
...

và kịch bản:

import sys
sys.path.append('k:/code')
from snippets import GetLibPath, NewObj, CType, OpenFeatureClass
sWorkingDir = "k:/code/"
sFileGDB = sWorkingDir + "blank_canvec.gdb"
sResourceDir = "k:/code/"
sFCAliasFile = sResourceDir + "fc_code-name_lookup.csv"
sAttAliasFile = sResourceDir + "att_code-name_lookup.csv"
sProduct = "ArcEditor"

def BuildFieldAliasLookup():
    lookup = {}
    f = open(sAttAliasFile, "r")
    bFirst = True
    for line in f:
        # Skip first line
        if bFirst:
            bFirst = False
            continue
        sTokens = line.replace('"','').split(',')
        sFieldName = sTokens[0]
        sAlias = sTokens[1]
        lookup[sFieldName] = sAlias
    return lookup

def AlterAlias():
    # Initialize
    from comtypes.client import GetModule
    import arcgisscripting
    sLibPath = GetLibPath()
    GetModule(sLibPath + "esriGeoDatabase.olb")
    GetModule(sLibPath + "esriDataSourcesGDB.olb")
    import comtypes.gen.esriGeoDatabase as esriGeoDatabase
    gp = arcgisscripting.create(9.3)

    try:
        gp.setproduct(sProduct)
    except:
        gp.AddMessage(gp.GetMessages(2))

    # Build field alias lookup table
    AttrLookup = BuildFieldAliasLookup()
    # Open alias file and loop through lines
    f = open(sFCAliasFile, "r")
    bFirst = True
    for line in f:
        # Skip first line
        if bFirst:
            bFirst = False
            continue
        sTokens = line.replace('"','').split(',')
        sFCName = sTokens[0]
        sAlias = sTokens[1]
        print "Processing: ", sFCName
        # Open feature class
        try:
            pFC = OpenFeatureClass(sFCName)
        except:
            print "Could not open ", sFCName
            continue
        # Alter feature class alias
        try:
            pSE = CType(pFC, esriGeoDatabase.IClassSchemaEdit)
            pSE.AlterAliasName(sAlias)
        except:
            print "Error altering class alias"
            continue
        # Alter field aliases
        try:
            for sKey in AttrLookup.keys():
                i = pFC.FindField(sKey)
                if i == -1:
                    continue
                sAlias = AttrLookup[sKey]
                pSE.AlterFieldAliasName(sKey, sAlias)
        except:
            print "Error altering field aliases"
    print "Done."

print 'Field <--> Alias lookup table is:', BuildFieldAliasLookup()
print AlterAlias()

Điều này rất gần với những gì tôi cần (cập nhật bí danh trường). Phần OpenFeatureClass của đoạn trích trông như thế nào? Mã của Mark không có đoạn đó. Cảm ơn

Xin chào Jasperoid: bạn có thể nhận xét về một câu trả lời cụ thể bằng cách nhấp vào liên kết 'thêm nhận xét', tôi đã di chuyển câu trả lời của bạn cho câu trả lời này.
scw

@Jasencies, tôi đã chuyển hầu hết các đoạn của Mark vào một mô-đun mà tôi gọi là parco , đó cũng là nơi OpenFeatureClass cũng vậy. Tôi không nhớ đã tự tạo ra nó, nhưng có lẽ tôi đã làm. Dù sao, nó ở dòng 125 .
matt wilkie

6

Mã này hoạt động với tôi trong 9.3.1 ...

public static void TestAlterAlias(IApplication app)
{
    // make a dictionary of old/new names
    Dictionary<string, string> nameDict = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
    nameDict.Add("qsectionalias", "qsectionalias2");
    nameDict.Add("sursysalias", "sursysalias2");
    string[] directories =  System.IO.Directory.GetDirectories(@"D:\Projects\EmpireOil\data",@"*.gdb",
        System.IO.SearchOption.TopDirectoryOnly);
    foreach(string dir in directories)
    {
        List<IName> fcnames = GetFCNames(dir);
        foreach (IName fcName in fcnames)
        {
            ChangeFieldAliases(fcName, nameDict);
        }
    }
}

public static void ChangeFieldAliases(IName fcName, Dictionary<string, string> aliasDict)
{
    IFeatureClass fc = (IFeatureClass)fcName.Open();
    IClassSchemaEdit3 cse = (IClassSchemaEdit3)fc;
    ((ISchemaLock)fc).ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock);
    SortedList<string, string> changeList = new SortedList<string, string>();
    for (int i = 0; i < fc.Fields.FieldCount; i++)
    {
        string fldName = fc.Fields.get_Field(i).Name;
        string alias = fc.Fields.get_Field(i).AliasName;
        if (aliasDict.ContainsKey(alias))
        {
            changeList.Add(fldName, aliasDict[alias]);
            // set it blank for now, to avoid problems if two fields have same aliasname.
            cse.AlterFieldAliasName(fldName, "");
        }
    }

    // change the alias
    foreach (KeyValuePair<string, string> kvp in changeList)
        cse.AlterFieldAliasName(kvp.Key, kvp.Value);
    ((ISchemaLock)fc).ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock);
}

public static List<IName> GetFCNames(string wsPath)
{
    List<IName> names = new List<IName>();
    IWorkspaceFactory wsf = new ESRI.ArcGIS.DataSourcesGDB.FileGDBWorkspaceFactoryClass();
    IWorkspace ws = wsf.OpenFromFile(wsPath, 0);
    IEnumDatasetName enumName = ws.get_DatasetNames(esriDatasetType.esriDTAny);
    enumName.Reset();
    IDatasetName dsName = null;
    while ((dsName = enumName.Next()) != null)
    {
        if(dsName is IFeatureClassName)
            names.Add((IName)dsName);
        else if(dsName is IFeatureDatasetName)
        {
            IEnumDatasetName enumName2 = dsName.SubsetNames;
            enumName2.Reset();
            IDatasetName dsName2;
            while((dsName2=enumName2.Next())!= null)
            {
                if(dsName2 is IFeatureClassName)
                    names.Add((IName)dsName2);
            }
        }
    }
    return names;
}

cảm ơn Kirk, bạn không biết tôi đã cố gắng tìm hiểu điều này bao lâu rồi. Tôi đoán đây là C #?
matt wilkie

1
Vâng C#. Mặc dù không thử nghiệm với tính năng đặc trưng, ​​nhưng sẽ hoạt động.
Kirk Kuykendall

3

Một giải pháp lịch sự khác của Rob Clark :

Bạn có thể sử dụng featureclass_to_featureclass với ánh xạ trường. Có, nó tạo ra một lớp tính năng khác nhưng bạn chỉ có thể có một khu vực đầu ra để sao chép dữ liệu và thay đổi bí danh trong khi thực hiện nó.

Hộp thoại FC đến FC với Thuộc tính mở (từ menu ngữ cảnh)

Trong python, cú pháp của field_mapphần này rất khó, vì vậy hãy lướt qua nó một lần để đặt các tham số thẳng, để cho nó chạy. Sau đó đi đến cửa sổ kết quả , nhấp chuột và Sao chép đoạn mã trăn . Dưới đây là một đoạn được kết hợp lại thành một cái gì đó dễ dàng hơn để mở rộng và sử dụng lại (có thể thực hiện nhiều công việc hơn để phá vỡ các phần của bản đồ trường và các thuộc tính):

inFC = 'e:/Canvec/fix.gdb/HD_1480009_2'
outFC = 'HD_with_aliases'
out_wspace = 'e:/canvec/fix.gdb'
where_clause = '#'      # use default
config_keyword = '#'    #    "

# build field map
fmap_out_att = 'CODE /\Specification code/\ '  # field and alias name
fmap_properties = 'true true false 4 Long 0 0 ,First,#,'  # field properties
fmap_in_att = 'e:/Canvec/fix.gdb/HD_1480009_2,CODE,-1,-1'  # input FC and field

# construct the complete field map
field_map = fmap_out_att + fmap_properties + fmap_in_att
   # results in:
   # "CODE /\Specification code/\ true true false 4 Long 0 0 ,First,#,e:/Canvec/fix.gdb/HD_1480009_2,CODE,-1,-1"


arcpy.FeatureClassToFeatureClass_conversion(inFC, out_wspace, outFC, 
        where_clause, field_map, config_keyword)

# the template command copied from Results window, used for building above
# arcpy.FeatureClassToFeatureClass_conversion("e:/Canvec/fix.gdb/HD_1480009_2","e:/canvec/fix.gdb","HD_with_aliases3","#","CODE /\Specification code/\ true true false 4 Long 0 0 ,First,#,e:/Canvec/fix.gdb/HD_1480009_2,CODE,-1,-1","#")

2

Giải pháp này dành cho người dùng sử dụng máy chủ SQL làm cơ sở dữ liệu địa lý. bạn có thể tự thay đổi nó bằng lệnh cập nhật SQL. tất cả các tính năng lưu tên trong bảng [sde]. [GDB_OBJECTCLASSES]. tên bí danh được đặt đơn giản nếu bạn thay đổi giá trị cột bí danh.

UPDATE [sde].[sde].[GDB_OBJECTCLASSES] 
SET AliasName = 'an alias name' 
WHERE Name='your feature class name'

EDIT: phương pháp này là phương pháp nhanh để thay đổi tên bí danh. nhưng sử dụng IClassSchemaEdit thì tốt hơn vì trong phương pháp cập nhật sql, bạn không thể sử dụng tên bí danh cho đến khi thiết lập lại không gian làm việc.

Public Sub SetAliasName(FeatureClass As IFeatureClass, AliasName As String)
        Dim abjTable As ITable = FeatureClass
        Dim objClass As IObjectClass = abjTable
        Dim edit As IClassSchemaEdit = objClass
        edit.AlterAliasName(AliasName)
End Sub

1
Bây giờ rõ ràng là tôi nghĩ về nó! Cách tiếp cận tương tự cũng có thể sử dụng GDB cá nhân (Access .mdb) hoặc bất kỳ tùy chọn lưu trữ RDBMS nào.
matt wilkie 10/2/2015

để tìm nó trong các RDBMS khác, tôi nghĩ tốt hơn là sao chép một bản sao lưu từ RDBMS của bạn và sau đó thay đổi tên bí danh bằng ArcCatalog sau đó so sánh cơ sở dữ liệu hiện tại với bản sao lưu mà bạn có thể thấy các thay đổi và tìm ra nơi lưu bí danh.
Mehdi
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.