Select to view content in your preferred language

Problems to rewrite a VBA script to Python

1573
10
03-15-2011 04:35 AM
JannWendt
Emerging Contributor
Hello,

maybe someone can help me to rewrite a VBA script to python. I'am new to this whole programming thing and I really need some help.

So I have a folder with several hundred image tiles, and an index.shp file that has a coordinate that represents the centroid of each image tile. In the attribute table for the index.shp, there is a field called Hyperlink, which specifies the full folder path and filename of each image on my hard disk.

What I am looking for is a tool/script that can look at which features of the index.shp I have manually selected, and then load the appropriate image tiles into ArcMap. I found this script below, but i need this script for python. And there are some problems to fix:
  
     - The shape file needs to be the top-most layer, but each time I run the python macro the newly loaded image is inserted on top. I then have to re-arrange the layers to run it again.

     - It is only possible to load one raster at the time. But I need several more rasters.


Private Sub LoadImageForSelectedFeat()

    Dim pMxDoc As IMxDocument
    Dim pMap As IMap
    Dim pFeatureLayer As IFeatureLayer
    Dim pFeatureSelection As IFeatureSelection
    Dim pFeatureCursor As IFeatureCursor
    Dim pSelectedFeature As IFeature
    Dim pSelectionSet As ISelectionSet
       
    Set pMxDoc = ThisDocument
    Set pMap = pMxDoc.FocusMap
    Set pFeatureLayer = pMap.Layer(0) ' Layer index of the shape file
    Set pFeatureSelection = pFeatureLayer
    Set pSelectionSet = pFeatureSelection.SelectionSet
   
    pSelectionSet.Search Nothing, False, pFeatureCursor
    Set pSelectedFeature = pFeatureCursor.NextFeature
   
    'I assume that you have single feature selected
    If Not pSelectedFeature Is Nothing Then
        Dim strFullPath As String
        strFullPath = pSelectedFeature.Value(pSelectedFeature.Fields.FindField("LOCATION"))  ' You can specify the field name from where you accessing the path
       
        Dim strPath As String
        Dim strFilename As String
        Dim strArray() As String
        Dim intI As Integer
       
        strArray = Split(strFullPath, "\")
        strFilename = strArray(UBound(strArray))
        strPath = Mid(strFullPath, 1, Len(strFullPath) - Len(strFilename))
               
        Dim pWorkspaceFactory As IWorkspaceFactory
        Set pWorkspaceFactory = New RasterWorkspaceFactory
       
        Dim pRasterWorkspace As IRasterWorkspace
        Set pRasterWorkspace = pWorkspaceFactory.OpenFromFile(strPath, 0)
       
        Dim pRasterDataset As IRasterDataset
        Set pRasterDataset = pRasterWorkspace.OpenRasterDataset(strFilename)
       
        Dim pRasterLayer As IRasterLayer
        Set pRasterLayer = New RasterLayer
        pRasterLayer.CreateFromDataset pRasterDataset
       
        pMap.AddLayer pRasterLayer
       
        pMxDoc.UpdateContents
        pMxDoc.ActiveView.Refresh
    End If
   
End Sub

I hope someone can help me!

Thanks in advance
Tags (2)
0 Kudos
10 Replies
MarkWiygul
Emerging Contributor
Someone with working experience in Python for ArcGIS will hopefully post a correction or additional information to this.  This may you started: 

I couldn't find anything in ArcToolbox or the Geoprocessor module but there is an ArcObject IMapControl2 method called 'MoveLayerTo' to that might (or might not) move the layers where one index location to another:   This method is listed on the diagram for
IMapControl2 : IDispatch
<---  (in fromIndex: Long, in toIndex: Long)

There is a little presentation titled "Using ArcObjects with Python" that points to additional sources.   If someone doesn't have a nifty procedure for get the layer moved without ArcObjects, then ArcObjects may be the answer.

EDIT UPDATE:  if you are using ArcGIS10 you should be about to use the ArcPY.mapping module and its 'MoveLayer' function to adjust the mxd layers.  That would be easier than dealing with ArcObjects. 

MoveLayer(data_frame, reference_layer, move_layer, {insert_position})

http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#//00170000006p000000.htm
0 Kudos
JannWendt
Emerging Contributor
I tried to study the help, but it's not very useful for me. I'm a completely beginner and all this is new to me.

Maybe there is someone who can post the python code

Greetings
0 Kudos
SeanCook
Emerging Contributor
Python geoprocessing tools only work on selected records, so you don't have to check to see if a record is selected, that is done automatically. This is also slightly annoying because arcpy can only add .lyr files. Yes, this is dumb and is why ESRI has no friends.

First thing first, make a .lyr files of all the image files:

import arcypy, glob

myImages = glob.glob('C:/YourDirectory/*.jpg') ## or whatever the extension is

for myImage in myImages:
~~image = arcpy.mapping.Layer(myImage)
~~imageAsLayer = image[:-3] + 'lyr' ## this cuts off the extension, and adds .lyr for the new filename
~~arcpy.mapping.SaveToLayerFile_management(image, imageAsLayer)



You should now have a .lyr file of each of your images.

You need to use cursors, something like the following to do your goal.

import arcpy

mxd = arcpy.mapping.MapDocument("Current")
df = arcpy.mapping.ListDataFrames(mxd)[0]

rows = arcpy.SearchCursor('c:/yourdirectory/index.shp')
fields = arcpy.ListFields('c:/yourdirectory/index.shp')

for row in rows:
~~for field in fields:
~~~~if field.name == 'Hyperlink':
~~~~~~value = row.getValue(field.name)
~~~~~~value = value[:-3] + 'lyr'
~~~~~~addLayer = arcpy.mapping.Layer(value)
~~~~~~arcpy.mapping.AddLayer(df, addLayer, "BOTTOM")



Keep in mind those squigglies are actually spaces or tabs, but I added them for formatting because I couldn't get spaces to stick and don't know how to add a code block.

The [:-3] bit is just a tool to cut up strings. That cuts 3 off the end. if your extension was .jpeg, make it [:-4]
0 Kudos
JannWendt
Emerging Contributor
But this is creating a new problem. All my raster data is georeferenced by TFW's and I guess that I will lose my reference if I create .lyr out of my image files...
0 Kudos
NiklasNorrthon
Frequent Contributor
But this is creating a new problem. All my raster data is georeferenced by TFW's and I guess that I will lose my reference if I create .lyr out of my image files...


Why do you think so?

A .lyr file is just a stored-to-disk version of what you have in the properties of a layer in the TOC. For image layers there is a reference to the .tif file, and there are display and symbology settings among other things.
0 Kudos
JannWendt
Emerging Contributor
Okay now I'm doing my first steps in python. I tried this:

to import arcypy, glob

myImages = glob.glob('C:/YourDirectory/*.jpg') ## or whatever the extension is

for myImage in myImages:
~~image = arcpy.mapping.Layer(myImage)
~~imageAsLayer = image[:-3] + 'lyr' ## this cuts off the extension, and adds .lyr for the new filename
~~arcpy.mapping.SaveToLayerFile_management(image, imageAsLayer)


But I get the error message "Runtime error <type 'exceptions.ValueError'>: Object: CreateObject Layer invalid data source"

Maybe you can help me out.

Thanks for all the help!
0 Kudos
SeanCook
Emerging Contributor
Ok, the method I gave you is a pain. Try this. Undoubtedly the second code won't work either, but lets see if you can get all the lyr files made.

First, open a clean arcmap 10 window, add all your image files and run this code:

import arcpy

mxd = arcpy.mapping.MapDocument("Current")
df = arcpy.mapping.ListDataFrames(mxd)[0]

layers = arcpy.mapping.ListLayers(mxd)
myDir = 'H:/Analysis/ESRI/Sean/Help/' ##the directory where you want your lyr files placed

for layer in layers:
[INDENT]    layerFile = myDir + str(layer) + 'lyr'
    arcpy.SaveToLayerFile_management(layer, layerFile) [/INDENT]
0 Kudos
MarkWiygul
Emerging Contributor
I'm going to make a guess at the cause of the 'value error': Try this if you are stuck. 

I think the value error may be resulting due to a format issue.  The 'myImage' objects could just be missing their proper string representation for use with the SaveToLayerFile_management method

try changing this line >>image = arcpy.mapping.Layer(myImage)<<

instead use this code >>image = arcpy.mapping.Layer(repr(myImage))<<

>>repr(anObject)<< returns a quoted representation

for instance, the value of >>myImage<< might be [without quotes] simply:
c:\yourDirectory\doqq22.lyr

and the value of >>repr(myImage)<< returns the canonical string representation of the object such as:
'c:\\yourDirectory\\doqq22.lyr'
0 Kudos
JannWendt
Emerging Contributor
Okay this works but now the next problem occurs...

Runtime error <type 'exceptions.TypeError'>:
'function' object is unsubscriptable

Any Solution?
0 Kudos