Getting map scale in standalone C# application.

08-23-2011 07:40 AM
New Contributor III
Hi everyone,

I am writing a standalone C# application for creating jpg maps that is being converted from VBA. With help from several people on the forums, I have been able to get everything working without having to use ArcMap at all. I am down to just one glitch and can't figure out how to get around it. At one point, I add a scalebar to the layout and depending on the map scale, I set the units of the scale bar to either esriMiles or esriFeet. The problem I am having is that since I am not running ArcMap and this is all being done in memory, I don't really have map scale to adjust.

In the code below, I get an error at if (m_pMap.MapScale >= 25000) with an error of "The data necessary to complete this operation is not yet available."

I have seen a couple of similar posts on the forums but no firm solutions. I have tried everything suggested on these threads including making sure the map has a spatial reference and units.

Later on in another method, I use the map scale also to set the scale to a rounded number (24,000 instead of 24,323) since the layout also has a scale text object.

How can I get/set the map scale if I am not using ArcMap?

Any help is greatly appreciated!!!

public static void AddScaleBar()
 stdole.StdFont pFont = new stdole.StdFont();
 pFont.Name = "Arial";

 ITextSymbol pTextSymbol = new TextSymbolClass();
 pTextSymbol.Font = pFont as stdole.IFontDisp;
 pTextSymbol.Size = 5;

 IGraphicsContainer pGraphicsContainer = m_pPageLayout as IGraphicsContainer;
 IFrameElement pFrameElement = pGraphicsContainer.FindFrame(m_pMap);
 IMapFrame mapFrame = pFrameElement as IMapFrame;

 IUID uid = new UIDClass();
 uid.Value = "esriCarto.AlternatingScaleBar";
 IMapSurroundFrame mapSurroundFrame = mapFrame.CreateSurroundFrame(uid as UID, null);
 IElement element = mapSurroundFrame as IElement;

 IEnvelope envelope = new EnvelopeClass();
 envelope.PutCoords(1.24, 0.4, 3.58, 0.55);
 element.Geometry = envelope;

 pGraphicsContainer.AddElement(element, 0);
 IMapSurround mapSurround = mapSurroundFrame.MapSurround;
 IScaleBar pScaleBar = mapSurround as IScaleBar;
 pScaleBar.Divisions = 1;
 pScaleBar.Subdivisions = 2;
 pScaleBar.DivisionsBeforeZero = 0;
 pScaleBar.LabelSymbol = pTextSymbol;
 pScaleBar.UnitLabelPosition = esriScaleBarPos.esriScaleBarBelow;
 pScaleBar.UnitLabelSymbol.HorizontalAlignment = esriTextHorizontalAlignment.esriTHACenter;
 pScaleBar.UnitLabelSymbol = pTextSymbol;
 pScaleBar.UnitLabelSymbol.Font = pFont as stdole.IFontDisp;
 pScaleBar.UnitLabelSymbol.Size = pTextSymbol.Size;
 pScaleBar.Name = "scalebar";

 //if map scale is greater than 25000, switch the scale units to miles
 if (m_pMap.MapScale >= 25000)
     pScaleBar.Units = esriUnits.esriMiles;
     pScaleBar.Units = esriUnits.esriFeet;

 IGraphicsContainerSelect pGraphicsContainerSelect = pGraphicsContainer as IGraphicsContainerSelect;
    catch (Exception ex)
0 Kudos
3 Replies
New Contributor II

Carlos Piccirillo Did you eventually get around this issue?

0 Kudos
New Contributor II

i have the same issue. Only when the Process runs in an background job, even if IMap is initialized. The IMap Object is not null, but the access to IMap.Mapscale aborts.

0 Kudos
New Contributor III

This is how I solved it.

/// <summary>

/// Purpose: Determine map scale once you are zoomed into the desired extent.

/// Cannot use m_pMap.MapScale because it cannot be used outside of ArcMap.

/// pMapFrame.MapBounds.Height is height of the DataFrame in feet and 7.8 is

/// the height of the DataFrame in inches. Before we calculate map scale, ground

/// distance needs to be in like units (inches), hence, pMapFrame.MapBounds.Height * 12.

/// </summary>

/// <returns>Int32</returns>

private static Int32 GetMapScale()


IMapFrame pMapFrame = new MapFrameClass();

IGraphicsContainer pGraphicsContainer = null;



pGraphicsContainer = m_pPageLayout as IGraphicsContainer;

pMapFrame = pGraphicsContainer.FindFrame(m_pMap) as IMapFrame;

double groundDistanceInInches = pMapFrame.MapBounds.Height * 12;

Int32 mapScale = Convert.ToInt32(groundDistanceInInches / 7.8);

return mapScale;


catch (Exception ex)


Queries.LogError(ex.StackTrace, ex.Message, "GetMapScale", "ensRegulatoryApplicationTools");

return 0;




if (pMapFrame != null) { Marshal.ReleaseComObject(pMapFrame); pMapFrame = null; }



0 Kudos