0

I'm writing a mapbasic create point statement and getting an argument out of range error when running the code. I've been though it a hundred times and can't figure out where my mistake is. I'm hoping some other eyes on the code might spot something that I'm missing. Basically the code assigns a create point function to a button on a toolbar; when the user clicks the button the cursor changes to crosshairs and when they click a point is created and a dialog opens where variables can be entered.

I'm only including the relevant declarations, etc. The error occurs right after the button on the toolbar is clicked (before the click event/point is created) and the line given on the error message is indicated in the syntax below:

Sub RefineryCreator

Dim sFeatureName, sDestTable, sAerialLoc, sSym, sOwnerName, sSource,
  sSourceDate as String 
Dim sOwner(), sOwnerID() as String 
Dim i, iOwner, iOwnerID, iStatus as Integer 
Dim lAerial as Logical 
Dim oObj as Object 
Dim fX, fY, fBCD as Float 
Dim symOne as Symbol 
Dim aOwner, aOwnerID as Alias

Open Table sAppPath + "data_files\oil_companies.tab" as refinery_owners     
Select * From refinery_owners Order by Company_Name Into _owners NoSelect   

ReDim sOwner(TableInfo(_owners, TAB_INFO_NROWS))    
aOwner = _owners + ".Company_Name"  
ReDim sOwnerID(TableInfo(_owners, TAB_INFO_NROWS))  
aOwnerID = _owners + ".Company_ID"  
For i = 1 to TableInfo(_owners, TAB_INFO_NROWS)         
   Fetch Rec i From _owners         
   sOwner(i) = aOwner       
   sOwnerID(i) = aOwnerID       
   If sOwner(i) = sOwnerName Then           
      iOwner = 1        
   End If   
Next    
Close Table refinery_owners         

symOne = MakeSymbol (34, 7585792, 12)       
fX = CommandInfo(CMD_INFO_X)    
fY = CommandInfo(CMD_INFO_Y)    

oObj = CreatePoint(fX,fY)       
Alter Object oObj       
   Info OBJ_INFO_SYMBOL, symOne

Dialog      
   Title "Create New Refinery"      
   Control StaticText           
      Title "Name:"             
      Position 5,0      
   Control EditText             
      Position 15,0   Width 100             
      Value ""          
      Into sFeatureName         
   Control StaticText           
      Position 5,20             
      Title "Owner:"        
   Control PopupMenu            
      Position 15,20            
      Title From Variable sOwner            
      Value iOwner          
      Into iOwner       
   Control CheckBox
      Position 5,40             
      Title "Aerial Imagery?"           
      Value lAerial             
      Into lAerial      
   Control RadioGroup           
      Position 5,55             
      Title "Proposed;Idle;Operating;Shutdown"          
      Into iStatus      
   Control StaticText           
      Title "BCD:"          
      Position 5,115        
   Control EditText
      Position 15,125   Width 15            
      Value ""          
      Into fBCD         
   Control StaticText                   
      Title "Source:"           
      Position 5,145        
   Control EditText
      Position 15,145    Width 100          
      Value ""          
      Into sSource      
   Control StaticText           
      Position 5,160            
      Title "Source Date:"      
   Control EditText             
      Position 30,160    Width 75           
      Value ""          
      Into sSourceDate          
   Control OKButton         
   Control CancelButton

If CommandInfo(CMD_INFO_DLG_OK) = FALSE then        
   Exit Sub     
ElseIf CommandInfo(CMD_INFO_DLG_OK) = TRUE then         
   sOwnerName = sOwner(iOwner)
   iOwnerID = sOwnerID(iOwner)  
End if      

sDestTable = "C:\work\oil_layers\Oil_Refineries_dev.TAB"    
If lAerial = TRUE and sSource <> "Aerial Imagery" then      
   sAerialLoc = "1"         
   Insert Into sDestTable 
      ( Name, Other_Name, Owner, Owner_ID, Previous_Owner, State, County
      , Zip_Code, Rank, BCD, Source, Loc_Code, Release_Source, Source_Date
      , Developer, Status, Notes, Last_Updated, Layer_ID, Rec_ID)
      Values 
      ( sFeatureName, "", sOwnerName, iOwnerID, "", "", "", "", ""
      , fBCD, "Aerial Imagery" + sSource, sAerialLoc, "Aerial Imagery"
      , sSourceDate, sUserName, iStatus, "", CurDate(), "915", "")  
Else
   Insert Into sDestTable 
      ( Name, Other_Name, Owner, Owner_ID, Previous_Owner, State, County
      , Zip_Code, Rank, BCD, Source, Loc_Code, Release_Source, Source_Date
      , Developer, Status, Notes, Last_Updated, Layer_ID, Rec_ID)           
      Values 
        (sFeatureName, "", sOwnerName, iOwnerID, "", "", "", "", ""
        , fBCD, sSource, "3", "ABB Research", sSourceDate, sUserName
        , iStatus, "", CurDate(), "915", "")        
   Commit Table sDestTable  
End If   

End Sub

(then a dialog is created where the user can assign variables for insertion into table, followed by the insert statement)

  • 1
    What sort of button is it that you've created? There are 3 types of buttons, PushButton, ToggleButton and ToolButton. It sounds like you should be using a ToolButton but may have chosen the wrong button type? – T_Bacon Sep 16 '16 at 7:43
  • It should be a PushButton type. I've used this code to make a similar tool that creates the same type of feature in a different .TAB. The only difference between the tables is that the other hits an oracle database and this table does not. Here is the code where the button is created on the toolbar: 'PushButton Calling RefineryCreator Icon MI_ICON_REALESTATE_7 HelpMsg "\nCreate a new refinery." – ta harp Sep 16 '16 at 20:00
  • It has to be a ToolButton, not a PushButton. – Peter Horsbøll Møller Sep 19 '16 at 6:46
1

It is very important that you read the values using CommandInfo as some of the very first things after the user has used your toolbutton.

I would recommand that you move the CommandInfo function calls to the top of your procedure before opening a table and looping thru this:

Sub RefineryCreator

Dim sFeatureName, sDestTable, sAerialLoc, sSym, sOwnerName, sSource, sSourceDate as String 
Dim sOwner(), sOwnerID() as String 
Dim i, iOwner, iOwnerID, iStatus as Integer 
Dim lAerial as Logical 
Dim oObj as Object 
Dim fX, fY, fBCD as Float 
Dim symOne as Symbol 
Dim aOwner, aOwnerID as Alias

'**Let's get the coordinate where the user clicked
fX = CommandInfo(CMD_INFO_X)    
fY = CommandInfo(CMD_INFO_Y) 

Open Table sAppPath + "data_files\oil_companies.tab" as refinery_owners     
Select * From refinery_owners Order by Company_Name Into _owners NoSelect   
...

It's for example not recommended that you first display a dialog and then read the coordinates afterwards.

From you code above I can't tell if this is done directly in the handler (the procedure) assigned to the ToolButton. But that really should be the case.

Also you might want to tell MapInfo Pro to use the coordinate system of the map when reading the coordinates.

It is almost important that this code is called from a toolbutton to make sure the user actually has clicked in a map window when you try to read the coordinates using CommandInfo()

  • Thanks for your reply Peter. i expanded the amount of quoted code to include the whole sub to see if that helps identify the problem (sorry for the lousy formatting, I havent quite figured the quoted text out yet). I've used this particular code to create features and insert data into the tables before, so I'm not sure why that tool works and this one does not. The only difference between the two tables is the other hits an oracle database and this one does not. – ta harp Sep 16 '16 at 20:22
1

It looks like the problem you are having is due to you using a PushButton rather than a ToolButton. In the documentation for the CommandInfo function the parameters specifying the map click locations (CMD_INFO_X and CMD_INFO_Y) are only used after either 1) a find operation, or 2) within a custom ToolButton handler. Attempting to use them outside of the scope of their intended use could result in the function returning incorrect data or, as in your case, a runtime error.

This should be a relatively easy fix. Change the button to a ToolButton which once toggled waits for the user to click on the map, depending on the draw mode you specify it may expect multiple clicks, before calling it's handler routine. I think in your case you want to use the draw mode DM_CUSTOM_POINT as you only want the coordinates of the point at which the user clicked. Then, in your handler routine, you can safely call the CommandInfo function with the CMD_INFO_X and CMD_INFO_Y parameters to get the coordinates for the click location.

Have a look at the Alter ButtonPad section of the MapBasic Reference Guide, specifically the section about Custom Drawing Modes, for more information.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.