Vous générez une liste de choix à valeurs multiples dans ArcGIS à l'aide de la validation d'outils sans utiliser la fréquence?

11

J'essaie d'adapter une combinaison de modèle et de script trouvée sur le site de blog d'ESRI intitulé «Génération d'une liste de choix à plusieurs valeurs».

Cependant, j'ai conclu qu'une partie de la validation utilisée dans le script intégré dépend de l'outil 'Frequency' pour fonctionner correctement, mais cela n'est disponible qu'avec une licence avancée (boiteuse). Le billet de blog explique le flux de travail et où télécharger les modèles et les scripts (mais je les publierai volontiers ici sur demande). Pour autant que je sache, le cœur de la fonctionnalité que je recherche, la génération d'une liste de choix à plusieurs valeurs:

entrez la description de l'image ici

..est basé sur le bon fonctionnement du script de validation. Sans la validation, je ne parviens pas à faire apparaître les valeurs du champ sous forme de liste. Y a-t-il quelque chose que je peux supprimer de ce script de validation pour obtenir les fonctionnalités que je recherche, ou existe-t-il une solution? Je ne connais pas le processus de validation. Voici le code pour la validation (j'allais poster en tant qu'échantillon de code, mais cela semble être plus facile à suivre): entrez la description de l'image ici

[ Note de l'éditeur: voici le code de validation actuel, l'image n'est pas correcte]

import arcpy

class ToolValidator(object):
  """Class for validating a tool's parameter values and controlling
  the behavior of the tool's dialog."""

  def __init__(self):
    """Setup arcpy and the list of tool parameters."""
    self.params = arcpy.GetParameterInfo()

  def initializeParameters(self):
    """Refine the properties of a tool's parameters.  This method is
    called when the tool is opened."""
    return

  def updateParameters(self):
    """Modify the values and properties of parameters before internal
    validation is performed.  This method is called whenever a parmater
    has been changed."""
    if self.params[1].altered: #Set condition - if the input field value changes
        if self.params[1].value: #if the field parameter has a value
            for field in arcpy.Describe(self.params[0].value).fields: #iterate through fields in the input dataset
                if field.name.lower() == self.params[1].value.value.lower(): #find the field object with the same name as field parameter
                    try:
                        if self.params[2].values: #if this parameter has seleted values
                            oldValues = self.params[2].values #set old values to the selected values
                    except Exception:
                        pass
                    values = set() #create an empty set
                    fieldname = self.params[1].value.value #set the value of variable fieldname equal to the input field value
                    FrequencyTable = arcpy.Frequency_analysis (self.params[0].value, "in_memory\Frequency", self.params[1].value.value, "") #for large tables create a frequency table
                    cursor = arcpy.SearchCursor(FrequencyTable, "", "", self.params[1].value.value, "{0} A".format(self.params[1].value.value)) #open a search cursor on the frequency table
                    for row in cursor: #loop through each value
                        values.add(row.getValue(fieldname)) #add the value to the set
                    self.params[2].filter.list = sorted(values) #set the filter list equal to the sorted values
                    newValues = self.params[2].filter.list
                    try:
                        if len(oldValues): # if some values are selected
                            self.params[2].values = [v for v in oldValues if v in newValues] # check if seleted values in new list,
                            # if yes, retain the seletion.
                    except Exception:
                        pass

  def updateMessages(self):
    """Modify the messages created by internal validation for each tool
    parameter.  This method is called after internal validation."""
    return

Est-il possible que mon hypothèse (via les tests) que la validation soit l'élément clé soit fausse et que quelque chose d'autre ne permette pas que les valeurs soient exposées en tant que liste sélectionnable? Merci d'avance. Avoir ce type de fonctionnalité va vraiment lancer l'adoption de plusieurs workflows clés que j'essaie de distribuer dans notre entreprise!

Clickinaway
la source
1
Quelle version d'ArcGIS utilisez-vous? Je demande parce qu'à 10,1 le arcpy.da.SearchCursorest beaucoup plus rapide et plus adapté à cette tâche que l'ancien arcpy.SearchCursor.
blah238
1
Le code de validation de la boîte à outils que vous avez liée est différent du code de validation de l'image que vous avez liée. Le premier nécessite une licence avancée car il utilise l'outil Frequency. Ce dernier, détaillé dans un article de blog précédent, ne devrait pas, car il utilise simplement des fonctions arcpy standard comme SearchCursor. Je n'ai pas de réponse pour vous, mais si vous assemblez les deux, vous pouvez peut-être le comprendre.
blah238
@ blah268 Son 10.2, désolé de l'avoir manqué. Hmm, maintenant c'est une observation très intéressante. Je vais regarder cela, mais je suis curieux: est-ce que je comprends bien que la validation est ce qui passe les valeurs comme liste de choix? le multi-choix étant la fonctionnalité que je recherche. Je vous répondrai et merci beaucoup pour la réponse!
Clickinaway
1
Les propriétés des paramètres de l'outil de script sont l'endroit où vous configurez la liste des paramètres et leurs propriétés (qui incluent une propriété MultiValue). La validation de l'outil de script est l'endroit où cet outil particulier remplit les valeurs de paramètres à valeurs multiples en fonction d'autres valeurs de paramètres (classe d'entités et nom de champ). Jouant avec pour des classes d'entités plus importantes, je ne mettrais pas cela en production. Trop lent, et aussi des erreurs si vous n'avez pas "Remplacer les sorties des opérations de géotraitement" coché dans les options de géotraitement.
blah238
1
Je ne suis pas en mesure de discuter, mais je suggérerais de modifier votre question pour détailler vos besoins, ce que vous avez essayé et ce qui ne fonctionne pas.
blah238

Réponses:

9

J'ai pensé que certaines personnes pourraient trouver cela précieux. ESRI a eu la gentillesse d'aider à résoudre ce problème et de trouver une alternative à la validation utilisée dans le billet de blog qui ne nécessite pas de licence avancée. Bien que je devais certainement trouver des éléments supplémentaires, je ne peux pas prendre le crédit pour le code de validation. Mais, les fins justifient les moyens et cela constitue la réponse à ma question. Voici:

import arcpy
class ToolValidator(object):
  """Class for validating a tool's parameter values and controlling
  the behavior of the tool's dialog."""

  def __init__(self):
    """Setup arcpy and the list of tool parameters."""
    self.params = arcpy.GetParameterInfo()

  def initializeParameters(self):
    """Refine the properties of a tool's parameters.  This method is
    called when the tool is opened."""
    return

  def updateParameters(self):
    """Modify the values and properties of parameters before internal
    validation is performed.  This method is called whenever a parameter
    has been changed."""
    if self.params[0].value and self.params[1].value:
        self.params[2].filter.list = sorted({row[0] for row in arcpy.da.SearchCursor(self.params[0].value, self.params[1].value.value) if row[0]})

  def updateMessages(self):
    """Modify the messages created by internal validation for each tool
    parameter.  This method is called after internal validation."""
    return

L'utilisation de l'arcpy.da.SearchCursor renvoie très rapidement les valeurs du champ choisi compte tenu du nombre d'enregistrements à rechercher (au moins dans mes données). Je peux commencer un nouveau fil pour voir si quelqu'un a des idées sur la façon d'appliquer un filtre à la validation basée sur une requête. J'espère que cela aide quelqu'un, mais je suis content que nous ayons une réponse!

Clickinaway
la source
1

Je l'ai fait d'une autre manière: l'utilisation de la base de données se compose de niveaux fixes, sans choisir le fichier de formes ou les champs simplement en sélectionnant des éléments du premier niveau, le script de validation génère les valeurs du deuxième niveau selon votre choix au premier niveau, elle le script:

import arcpy
class ToolValidator(object):
  """Class for validating a tool's parameter values and controlling
  the behavior of the tool's dialog."""

  def __init__(self):  
    """Setup arcpy and the list of tool parameters."""  
    self.params = arcpy.GetParameterInfo()  



  def initializeParameters(self):  
    """Refine the properties of a tool's parameters.  This method is  
    called when the tool is opened."""  
    return  

  def updateParameters(self):

    fc="C:/LUCS/System_shapes/sys.shp"
##    fc = arcpy.MakeFeatureLayer_management(Lucssys)  
    """Modify the values and properties of parameters before internal  
    validation is performed.  This method is called whenever a parmater  
    has been changed."""  
##    if self.params[0].value and self.params[0].value:


    fc="C:/LUCS/System_shapes/sys.shp"  
    col=  ("L1_NAM") 
    self.params[0].filter.list = [str(val) for val in  
                                    sorted(  
                                      set(  
                                        row.getValue(col)  
                                        for row in arcpy.SearchCursor(fc, None, None,col)))]  
    if self.params[0].value not in self.params[0].filter.list:  
      self.params[0].value = self.params[0].filter.list[0]


    if self.params[0].value:

        fc="C:/LUCS/System_shapes/sys.shp"  
        col1=  ("L1_NAM")
        col2=  ("L2_NAM") 
        fields=(col1,col2)
##___________level2___________________________________________________________
    fc="C:/LUCS/System_shapes/sys.shp" 
    col1=  ("L1_NAM")
    col2=  ("L2_NAM") 
    fields=(col1,col2)

    Level0list=[]
    Level0list_uniq=[]
    cursor = arcpy.SearchCursor(fc)
    for row in cursor:
              if (row.getValue(col1)) ==(str(self.params[0].value)):
                      Level0list.append (row.getValue(col2))

    for elem in Level0list:
              if elem not in Level0list_uniq:
                  Level0list_uniq.append(elem)


    if self.params[1].value not in self.params[1].filter.list:  
        self.params[1].filter.list =Level0list_uniq
##________________level3______________________________________________________        
    fc="C:/LUCS/System_shapes/sys.shp" 
    col2=  ("L2_NAM")
    col3=  ("L3_NAM") 
    fields=(col2,col3)
    Level2list=[]
    Level2list_uniq=[]
    cursor = arcpy.SearchCursor(fc)
    for row in cursor:
              if (row.getValue(col2)) ==(str(self.params[1].value)):
                      Level2list.append (row.getValue(col3))
    for elem in Level2list:
              if elem not in Level2list_uniq:
                  Level2list_uniq.append(elem)
    if self.params[2].value not in self.params[2].filter.list:  
        self.params[2].filter.list =Level2list_uniq
##________________level4______________________________________________________        
    fc="C:/LUCS/System_shapes/sys.shp" 
    col3=  ("L3_NAM")
    col4=  ("L4_NAM") 
    fields=(col3,col4)

    Level3list=[]
    Level3list_uniq=[]
    cursor = arcpy.SearchCursor(fc)
    for row in cursor:
              if (row.getValue(col3)) ==(str(self.params[2].value)):
                      Level3list.append (row.getValue(col4))
    for elem in Level3list:
              if elem not in Level3list_uniq:
                  Level3list_uniq.append(elem)
    if self.params[3].value not in self.params[3].filter.list:  
        self.params[3].filter.list =Level3list_uniq
##________________level5______________________________________________________        
    fc="C:/LUCS/System_shapes/sys.shp" 
    col4=  ("L4_NAM")
    col5=  ("L5_NAM") 
    fields=(col4,col5)

    Level4list=[]
    Level4list_uniq=[]
    cursor = arcpy.SearchCursor(fc)
    for row in cursor:
              if (row.getValue(col4)) ==(str(self.params[3].value)):
                      Level4list.append (row.getValue(col5))
    for elem in Level4list:
              if elem not in Level4list_uniq:
                  Level4list_uniq.append(elem)
    if self.params[4].value not in self.params[4].filter.list:  
        self.params[4].filter.list =Level4list_uniq

  def updateMessages(self):  
    """Modify the messages created by internal validation for each tool  
    parameter.  This method is called after internal validation."""  
Younes Idriss
la source
0
Add new conditions to ensure a single option when the same term exists in more than one category. ِand to force arcpy to deal with arabic fonts

import arcpy
import sys

reload(sys)

sys.setdefaultencoding('utf-8')

class ToolValidator(object):
  """Class for validating a tool's parameter values and controlling
  the behavior of the tool's dialog."""



  def __init__(self):  
    """Setup arcpy and the list of tool parameters."""  
    self.params = arcpy.GetParameterInfo()  




  def updateParameters(self):

    fc="C:/LUCS/System_shapes/sys.shp"
    col=  ("L1_NAM")
 ##________________level1_________________

    self.params[0].filter.list = [str(val) for val in  
                                    sorted(  
                                      set(  
                                        row.getValue(col)  
                                        for row in arcpy.SearchCursor(fc, None, None,col)))]  
    if self.params[0].value not in self.params[0].filter.list:  
      self.params[0].value = self.params[0].filter.list[0]



    if self.params[0].value:

        fc="C:/LUCS/System_shapes/sys.shp"  
        col1=  ("L1_NAM")
        col2=  ("L2_NAM")
        col3=  ("L3_NAM") 
        col4=  ("L4_NAM")
        col5=  ("L5_NAM") 
        fields=(col1,col2,col3,col4,col5)
        Level1list=[]
        Level1list_uniq=[]
        Level2list=[]
        Level2list_uniq=[]
        Level3list=[]
        Level3list_uniq=[]
        Level4list=[]
        Level4list_uniq=[]
        Level5list=[]
        Level5list_uniq=[]

        cursor = arcpy.SearchCursor(fc)
        for row in cursor:
                        if (row.getValue(col1)) ==(str(self.params[0].value)):
                                Level1list.append (row.getValue(col2))

        for elem in Level1list:
                        if elem not in Level1list_uniq:
                            Level1list_uniq.append(elem)


        if self.params[1].value not in self.params[1].filter.list:  
              self.params[1].filter.list =Level1list_uniq
      ##________________level3_________________        
        cursor = arcpy.SearchCursor(fc)
        for row in cursor:
                  if (row.getValue(col1)) ==(str(self.params[0].value)):
                    if (row.getValue(col2)) ==(str(self.params[1].value)):
                            Level2list.append (row.getValue(col3))
        for elem in Level2list:
                    if elem not in Level2list_uniq:
                        Level2list_uniq.append(elem)
        if self.params[2].value not in self.params[2].filter.list:  
              self.params[2].filter.list =Level2list_uniq
      ##________________level4_______________       
        cursor = arcpy.SearchCursor(fc)
        for row in cursor:
              if (row.getValue(col1)) ==(str(self.params[0].value)):

                    if (row.getValue(col3)) ==(str(self.params[2].value)):
                            Level3list.append (row.getValue(col4))
        for elem in Level3list:
                    if elem not in Level3list_uniq:
                        Level3list_uniq.append(elem)
        if self.params[3].value not in self.params[3].filter.list:  
              self.params[3].filter.list =Level3list_uniq
      ##________________level5_______________      
        cursor = arcpy.SearchCursor(fc)
        for row in cursor:
            if (row.getValue(col1)) ==(str(self.params[0].value)):
                    if (row.getValue(col4)) ==(str(self.params[3].value)):
                            Level4list.append (row.getValue(col5))
        for elem in Level4list:
                    if elem not in Level4list_uniq:
                        Level4list_uniq.append(elem)
        if self.params[4].value not in self.params[4].filter.list:  
              self.params[4].filter.list =Level4list_uniq

    return
Younes Idriss
la source
Veuillez formater correctement tout votre code.
Marcelo Villa-Piñeros
il a été fait, son travail en 10.5.0
Younes Idriss
Une partie de votre code est formatée, mais comme vous pouvez le voir, d'autres lignes ne le sont pas ( par exemple les instructions d'importation de votre code). Utilisez le { }bouton pour formater correctement votre code.
Marcelo Villa-Piñeros
Il semble également que la définition d'une classe vous manque.
Marcelo Villa-Piñeros