Original Message:
Sent: 03-10-2026 11:27
From: Mayca González Pérez
Subject: MapBasic Monday: Add a Legend to a Layout Through MapBasic
It's working now. Thanks. One more question: could I add UTM coordinates to the map border?
------------------------------
Mayca González Pérez
COMUNIDAD. AUT. REG MURCIA
Original Message:
Sent: 03-03-2026 03:06
From: Peter Møller
Subject: MapBasic Monday: Add a Legend to a Layout Through MapBasic
I'm sorry, but that doesn't give me enough context to help you out.
The source code does look fine from what I can tell.
Is the fourth layer a normal layer type? IS there anything with that layer that is different from the first few layers?
------------------------------
Peter Horsbøll Møller
Principal Presales Consultant | Distinguished Engineer
Precisely | Trust in Data
Original Message:
Sent: 03-03-2026 02:42
From: Mayca González Pérez
Subject: MapBasic Monday: Add a Legend to a Layout Through MapBasic

------------------------------
Mayca González Pérez
COMUNIDAD. AUT. REG MURCIA
Original Message:
Sent: 03-03-2026 02:32
From: Peter Møller
Subject: MapBasic Monday: Add a Legend to a Layout Through MapBasic
Your MapBasic code must be slightly different from mine. I don't have a line 268, so I can't tell where it is failing.
Can you upload your tematicos.mb as a zip file? I will have a look.
It does seem to generate at least some legends for you, right?
Does it fail after it has finished generating all the legends? Or does it fail during generating them?
------------------------------
Peter Horsbøll Møller
Principal Presales Consultant | Distinguished Engineer
Precisely | Trust in Data
Original Message:
Sent: 03-03-2026 02:23
From: Mayca González Pérez
Subject: MapBasic Monday: Add a Legend to a Layout Through MapBasic
I get the following error: Invalid frame ID 4

------------------------------
Mayca González Pérez
COMUNIDAD. AUT. REG MURCIA
Original Message:
Sent: 03-02-2026 02:49
From: Peter Møller
Subject: MapBasic Monday: Add a Legend to a Layout Through MapBasic
Last week, @Mayca González Pérez raised a question about inserting legends into his layout using MapBasic.
I gave a generic answer, but it can be a bit hard to adapt it to fit his MapBasic code and variable names. So today, I decided to adapt my code to his.
The resulting layout looks like this.
Let me walk you through the steps:
The existing code already created a frame for the map window and inserted a clone of an existing map window into it.
I just added a single line of code to this to capture the ID of the frame holding the main map
nMapFrameID = LayoutInfo(nLayoutID, LAYOUT_INFO_NUM_ITEMS)
I need this later on to be able to insert the legends over this frame.
Capture the Location of the Map Window Frame
I use the Frame ID that I captured above to now find the location of the top left corner of this frame. I also capture the heigh and width of the frame.
'## Finding the top left corner of the map frame and inserting the legends from this locationfFrameX = LayoutItemInfo(nLayoutID, nMapFrameID, LAYOUT_ITEM_INFO_POS_X)fFrameY = LayoutItemInfo(nLayoutID, nMapFrameID, LAYOUT_ITEM_INFO_POS_Y)fFrameWidth = LayoutItemInfo(nLayoutID, nMapFrameID, LAYOUT_ITEM_INFO_WIDTH)fFrameHeight = LayoutItemInfo(nLayoutID, nMapFrameID, LAYOUT_ITEM_INFO_HEIGHT)fFramePositionY = fFrameY
These values will be used to position the legends as I start inserting these.
This also means that if you want to place your legends elsewhere on the layout, you can set a different position here.
Inserting the Legends
Now I loop over the layers in the main map window and create a legend for each of these, as long as they are normal layers or thematic layers.
For the first layer, I use Create Designer Legend:
Create Designer Legend From Window nMapIDInLayout Default Frame Style "#" Font ("Arial",0,8,0) Custom Frame From Layer nLayer Position (fFrameX, fFramePositionY) Units "in" Using Column Object Label defaultnLegendWID = LayoutItemInfo(nLayoutID, LayoutInfo(nLayoutID, LAYOUT_INFO_NUM_ITEMS), LAYOUT_ITEM_INFO_LEGEND_DESIGNER_WINDOW)
I set the Default Frame Style, which will affect the other legends created as well.
I use the current values for the legends to position the legend, and I set it to use the Object to control the style.
Finally, I read the Legend Window ID, so that I can reference this for the remaining layers.
For the remaining layers, I use Add Designer Frame to add to the existing frame; otherwise, it uses the same legend settings:
Add Designer Frame Window nLegendWID Custom Frame From Layer nLayer Position (fFrameX, fFramePositionY) Units "in" Using Column Object Label default
Finally, I capture and calculate the position of the next frame and the maximum width of the frames so far.
fFramePositionY = fFramePositionY + LayoutItemInfo(nLayoutID, LayoutInfo(nLayoutID, LAYOUT_INFO_NUM_ITEMS), LAYOUT_ITEM_INFO_HEIGHT)fLegendWidth = LayoutItemInfo(nLayoutID, LayoutInfo(nLayoutID, LAYOUT_INFO_NUM_ITEMS), LAYOUT_ITEM_INFO_WIDTH)fLegendWidthMax = Maximum(fLegendWidthMax, fLegendWidth)
Here is the full source code related to inserting legends:
'## Inserting a legend for each layer in the mapnNumLayers = MapperInfo(nMapIDInLayout, MAPPER_INFO_LAYERS)For nLayer = 1 to nNumLayers If LayerInfo(nMapIDInLayout, nLayer, LAYER_INFO_TYPE) In (LAYER_INFO_TYPE_NORMAL, LAYER_INFO_TYPE_THEMATIC) Then sLayerAlias = LayerInfo(nMapIDInLayout, nLayer, LAYER_INFO_ALIAS) Print nLayer & ". Layer Alias: " & sLayerAlias 'Create Designer Legend ' From Window 3018 ' Portrait ' Default Frame Style "Stores" Font ("Arial",0,8,0) ' Frame ' From Layer 1 Using column object label default If nLegendWID = 0 Then Create Designer Legend From Window nMapIDInLayout Default Frame Style "#" Font ("Arial",0,8,0) Custom Frame From Layer nLayer Position (fFrameX, fFramePositionY) Units "in" Using Column Object Label default nLegendWID = LayoutItemInfo(nLayoutID, LayoutInfo(nLayoutID, LAYOUT_INFO_NUM_ITEMS), LAYOUT_ITEM_INFO_LEGEND_DESIGNER_WINDOW) Else Add Designer Frame Window nLegendWID Custom Frame From Layer nLayer Position (fFrameX, fFramePositionY) Units "in" Using Column Object Label default End If fFramePositionY = fFramePositionY + LayoutItemInfo(nLayoutID, LayoutInfo(nLayoutID, LAYOUT_INFO_NUM_ITEMS), LAYOUT_ITEM_INFO_HEIGHT) fLegendWidth = LayoutItemInfo(nLayoutID, LayoutInfo(nLayoutID, LAYOUT_INFO_NUM_ITEMS), LAYOUT_ITEM_INFO_WIDTH) fLegendWidthMax = Maximum(fLegendWidthMax, fLegendWidth) End IfNext 'nLayer
I ned the creation of the legends by inserting a rectangle under the legends so that the map underneath is hidden.
'## Create frame to sit behind legend and create white spaceCreate Rect (fFrameX, fFrameY) (fFrameX + fLegendWidthMax, fFramePositionY) Pen (1,2,0) Brush (2,16777215,16777215) Priority 1
Variables
I also added several variables, which I merged into the existing variables of the program.
Below, you can see the variables that I added without the existing variables:
Dim nMapFrameID, nLayer, nNumLayers, nLegendWID As IntegerDim sLayerAlias as StringDim fFrameX, fFrameY, fFramePositionY, fFrameWidth, fFrameHeight, fLegendWidth, fLegendWidthMax As Float
The Final Source Code
Here is the full adapted sourcecode. I have also attached the full source code in the form of a zipped mb file.
I had to comment out a few calls to additional procedures that I didn't have access to, to make the program run.
I also commented out the creation of the logo map and the north arrow map. I would suggest inserting the logo as an image, as that is now supported. The north arrow can be inserted as a point with a north arrow symbol if you prefer.
Include "MapBasic.def"Declare Sub MainDeclare Sub TEMATICO_INFRAESTR_VIARIADim gblNOMBRE_MUNICIPIO, gblNOMBRE_NUCLEO As StringDim num_win_localizacion As IntegerSub Main Call TEMATICO_INFRAESTR_VIARIAEnd SubSub TEMATICO_INFRAESTR_VIARIAOnError GoTo errorTematicoViaria'1) Cargar configuración guardada'2) Cargar parámetros geométricos'3) Crear layout con tamaño correcto'4) Aplicar formato impresora'5) Insertar frames usando coordenadas parametrizadasDim nMapID, nMapIDInLayout, nLayoutID, nLegendID, nMapFrameID, nLayer, nNumLayers, i, nLegendWID As IntegerDim strTitulo, strStatement, cmdstr, str_tit_principal, str_tit_leyenda, sLayerAlias as StringDim fFrameX, fFrameY, fFramePositionY, fFrameWidth, fFrameHeight, fLegendWidth, fLegendWidthMax As FloatstrTitulo = "MUNICIPIO: "+gblNOMBRE_MUNICIPIO+chr$(13)+"NÚCLEO:"+gblNOMBRE_NUCLEO'Call CARGAR_PARAM_TEMATICOS'Set Printer Name gblThematicPrinter''##### ASIGNANDO NOMBRE DEL MUNICIPIO ENCUESTADO Y RUTA DE ARCHIVOS ###############'Call TEMATICO_CARGAR_PARAMETROSstr_tit_principal = WindowInfo(FrontWindow(), WIN_INFO_NAME)'**Let's find a map window to insertFor i = 1 To NumWindows() If WindowInfo(WindowID(i), WIN_INFO_TYPE) = WIN_MAPPER Then nMapID = WindowID(i) Exit For End IfNextPrint "Map: " & WindowInfo(nMapID, WIN_INFO_NAME)num_win_localizacion = nMapIDDim strMapName As StringDim strMunicipio As StringDim strNucleo As StringDim strTematico As StringDim posGuion As IntegerDim posAsterisco As IntegerstrMapName = WindowInfo(nMapID, WIN_INFO_NAME)posGuion = InStr(1, strMapName, " - ")posAsterisco = InStr(1, strMapName, "*")If posGuion > 0 Then strMunicipio = Left$(strMapName, Len(posGuion) - 1)End IfIf posAsterisco > 0 Then strNucleo = Mid$(strMapName, posGuion + 3, posAsterisco - (Len(posGuion) + 3)) strTematico = Mid$(strMapName, posAsterisco + 1, Len(strMapName) - posAsterisco)End If'Create Layout windowLayout Designer Position (0.0,0.0) Units "in"' Width pWidth Height pHeight Units "in"nLayoutID = FrontWindow()Set Layout Window nLayoutID Extents To Fit Zoom 100Set CoordSys Layout Units "in"Set Paper Units "In"'Call TEMATICO_FORMATO_IMPRIMIR_PAPELDim ancho As FloatDim alto As Floatancho = LayoutInfo(nLayoutID, LAYOUT_INFO_WIDTH)alto = LayoutInfo(nLayoutID, LAYOUT_INFO_HEIGHT)Dim margen As FloatDim franja As FloatDim banda As Floatmargen = ancho * 0.03 ' 3% margenfranja = ancho * 0.18 ' 18% franja derechabanda = alto * 0.10 ' 10% banda superior'Insert Map into LayoutCreate Frame Into Window nLayoutID (margen, margen) (ancho-franja, alto-banda) 'Pen (1,2,0) Brush (2, 16777215, 16777215) From Window nMapID FillFrame OnnMapIDInLayout = WindowID(0)nMapFrameID = LayoutInfo(nLayoutID, LAYOUT_INFO_NUM_ITEMS)'num_win_principal = nMapID'Call TEMATICO_CAPAS_AUXILIARESDim colX1 As FloatDim colX2 As FloatDim zonaY1 As FloatDim zonaY2 As FloatDim bloqueAltura As FloatDim logoY1 As FloatDim logoY2 As FloatDim textoY1 As FloatDim textoY2 As FloatlogoY1 = zonaY1logoY2 = zonaY2 - 2*bloqueAlturatextoY1 = logoY2textoY2 = logoY2 + (bloqueAltura * 0.40)colX1 = ancho - franja + margen/2colX2 = ancho - margen/2zonaY1 = margenzonaY2 = alto - bandabloqueAltura = (zonaY2 - zonaY1) / 3Dim alturaTotal As FloatDim hLoc As FloatDim hNorte As FloatDim hLogo As FloatDim hTexto As FloatcolX1 = ancho - franja + margen/2colX2 = ancho - margen/2zonaY1 = margenzonaY2 = alto - bandaalturaTotal = zonaY2 - zonaY1hLoc = alturaTotal * 0.35hNorte = alturaTotal * 0.20hLogo = alturaTotal * 0.25hTexto = alturaTotal * 0.20Dim yActual As FloatyActual = zonaY2'LOCALIZACIÓN'Create Frame Into Window nLayoutID (colX1, zonaY2 - 2*bloqueAltura) (colX2, zonaY2)Create Frame Into Window nLayoutID (colX1, yActual - hLoc) (colX2, yActual) Pen (1,2,0) Brush (2,16777215,16777215) From Window num_win_localizacion FillFrame OnyActual = yActual - hLoc'NORTE'Create Frame Into Window nLayoutID (colX1, zonaY2 - 2*bloqueAltura) (colX2, zonaY2 - bloqueAltura)'Create Frame Into Window nLayoutID (colX1, yActual - hNorte) (colX2, yActual)' Pen (1,2,0)' Brush (2,16777215,16777215)' From Window num_win_norte' FillFrame On'yActual = yActual - hNorte'LOGO'Create Frame Into Window nLayoutID (colX1, zonaY1) (colX2, zonaY2 - 2*bloqueAltura)'Create Frame Into Window nLayoutID (colX1, yActual - hLogo) (colX2, yActual)' Pen (1,2,0)' Brush (2,16777215,16777215)' From Window num_win_logo' FillFrame OnyActual = yActual - hLogo'MUNICIPIOCreate Rect Into Window nLayoutID (colX1, zonaY1) (colX2, yActual) Pen (1,2,0) Brush (2,16777215,16777215)Create Text Into Window nLayoutID "MAPA TEMÁTICO: " + UCase$(strTematico) + Chr$(13) + Chr$(13) + "MUNICIPIO: " + gblNOMBRE_MUNICIPIO + Chr$(13) + "NÚCLEO: " + gblNOMBRE_NUCLEO (colX1, zonaY1) (colX2, yActual) Font ("Arial",1,9,1) Justify Center'Set Map Window nMapIDInLayout Zoom Entire Layer SelectionIf WindowInfo(nMapIDInLayout, WIN_INFO_TYPE) <> WIN_MAPPER Then Note "La ventana activa no es un mapa" Exit SubEnd If'## Finding the top left corner of the map frame and inserting the legends from this locationfFrameX = LayoutItemInfo(nLayoutID, nMapFrameID, LAYOUT_ITEM_INFO_POS_X)fFrameY = LayoutItemInfo(nLayoutID, nMapFrameID, LAYOUT_ITEM_INFO_POS_Y)fFrameWidth = LayoutItemInfo(nLayoutID, nMapFrameID, LAYOUT_ITEM_INFO_WIDTH)fFrameHeight = LayoutItemInfo(nLayoutID, nMapFrameID, LAYOUT_ITEM_INFO_HEIGHT)fFramePositionY = fFrameY'## INserting a legend for each layer in the mapnNumLayers = MapperInfo(nMapIDInLayout, MAPPER_INFO_LAYERS)For nLayer = 1 to nNumLayers If LayerInfo(nMapIDInLayout, nLayer, LAYER_INFO_TYPE) In (LAYER_INFO_TYPE_NORMAL, LAYER_INFO_TYPE_THEMATIC) Then sLayerAlias = LayerInfo(nMapIDInLayout, nLayer, LAYER_INFO_ALIAS) Print nLayer & ". Layer Alias: " & sLayerAlias 'Create Designer Legend ' From Window 3018 ' Portrait ' Default Frame Style "Stores" Font ("Arial",0,8,0) ' Frame ' From Layer 1 Using column object label default If nLegendWID = 0 Then Create Designer Legend From Window nMapIDInLayout Default Frame Style "#" Font ("Arial",0,8,0) Custom Frame From Layer nLayer Position (fFrameX, fFramePositionY) Units "in" Using Column Object Label default nLegendWID = LayoutItemInfo(nLayoutID, LayoutInfo(nLayoutID, LAYOUT_INFO_NUM_ITEMS), LAYOUT_ITEM_INFO_LEGEND_DESIGNER_WINDOW) Else Add Designer Frame Window nLegendWID Custom Frame From Layer nLayer Position (fFrameX, fFramePositionY) Units "in" Using Column Object Label default End If fFramePositionY = fFramePositionY + LayoutItemInfo(nLayoutID, LayoutInfo(nLayoutID, LAYOUT_INFO_NUM_ITEMS), LAYOUT_ITEM_INFO_HEIGHT) fLegendWidth = LayoutItemInfo(nLayoutID, LayoutInfo(nLayoutID, LAYOUT_INFO_NUM_ITEMS), LAYOUT_ITEM_INFO_WIDTH) fLegendWidthMax = Maximum(fLegendWidthMax, fLegendWidth) End IfNext 'nLayer'## Create frame to sit behind legend and create white spaceCreate Rect (fFrameX, fFrameY) (fFrameX + fLegendWidthMax, fFramePositionY) Pen (1,2,0) Brush (2,16777215,16777215) Priority 1DONE: Exit SuberrorTematicoViaria: Note "ERROR:" + Chr$(13) + Error$() Exit SubEnd Sub
------------------------------
Peter Horsbøll Møller
Principal Presales Consultant | Distinguished Engineer
Precisely | Trust in Data
------------------------------