Select to view content in your preferred language

Labelling: Multiline Labelling Using 1 Field

1625
3
12-20-2023 09:29 AM
Labels (1)
CiaraMarleneKeenan
Occasional Contributor

-Goal: Create Multiline Labelling using 1 Field

-My workflow: I found an Arcade script on ESRI’s Technical support page that works pretty well. I don’t know if it makes a difference but I am working in AGOL for this project.  How To: Create Multiline Labels for a Single Field in ArcGIS Online Map Viewer (esri.com)

-Problem: The script doesn’t return 2 labels with “ Water Service Area” at the end of the label, however it returns the others.  The other issue is when I try to add another variable for “ Water Company” or “ Retail Service Area” the script doesn’t return those as well or even the label at all. The script did accept “ Mutual Water Company” and return the label properly. Based on ESRI’s example, I thought there could be repeating words for the Find functions?

Question: Is there a way that I can still use this script + another script for the front part of the label? I don’t want to do the whole script for the front part of the label because then I would have to make a lot of variables.

Arcade Script

function FormatName(name, split_pt) {

  var front = Left(name, split_pt);

  var back = Right(name, Count(name) - (split_pt + 1));

  var front_len = Count(front);

  var back_len = Count(back);

  var spacing = "";

  var adjust = 1.3;

 

  if (front_len < back_len) {

    spacing = Concatenate(Array(Ceil(((back_len - front_len) / 2) * adjust), " "));

    return spacing + front + TextFormatting.NewLine + back;

  } else {

    if (back_len < front_len) {

      spacing = Concatenate(Array(Ceil(((back_len - front_len) / 2) * adjust), " "));

      return front + TextFormatting.NewLine + spacing + back;

    } else {

      return front + TextFormatting.NewLine + back;

    }

  }  

}

 

var Agency = $feature.AgencyName2;

var WSA = Find(" Water Service Area", Agency);

var RPU = Find(" Riverside Public Utilities (RPU)", Agency);

var SB = Find(" San Bernardino", Agency);

var MWC = Find(" Mutual Water Company", Agency);

 

if (WSA != -1) {

  return FormatName(Agency, WSA);

} else {

  if (RPU != -1) {

    return FormatName(Agency, RPU );

  } else {

    if (SB != -1){

      return FormatName(Agency, SB);

    } else {

      if (MWC != -1) {

        return FormatName(Agency, MWC)

      } else {

      }

      return Agency;

      }

    }

  }

 

Thank You 😊

0 Kudos
3 Replies
KenBuja
MVP Esteemed Contributor

You can replace all your if statements by looping through an array of the possible agencies

function FormatName(name, split_pt) {
  var frontend = Left(name, split_pt);
  var backend = Right(name, Count(name) - (split_pt + 1));
  var front_len = Count(frontend);
  var back_len = Count(backend);
  var spacing = "";
  var adjust = 1.3;

  if (front_len < back_len) {
    spacing = Concatenate(Array(Ceil(((back_len - front_len) / 2) * adjust), " "));
    return spacing + frontend + TextFormatting.NewLine + backend;
  } else {
    if (back_len < front_len) {
      spacing = Concatenate(Array(Ceil(((back_len - front_len) / 2) * adjust), " "));
      return frontend + TextFormatting.NewLine + spacing + backend;
    } else {
      return frontend + TextFormatting.NewLine + backend;
    }
  }  
}

var Agency = $feature.AgencyName2;
var names = [
  " Water Service Area",
  " Riverside Public Utilities (RPU)",
  " San Bernardino",
  " Mutual Water Company",
];

for (var i in names) {
  var sb = Find(names[i], Agency)
  if (sb > -1) return FormatName(Agency, sb)
}
return "Agency not found"
CiaraMarleneKeenan
Occasional Contributor

Thank you for streamlining the code for me. Actually, with the help of an IT colleague, we found out that lines 10 & 14 have a bug. But I found a solution!!

1. I flip flopped the back_len/ front_len parts of line 10 & 14 so that both scenarios are covered. *Without doing this some labels would be shown and some would not be shown even though they have the same variable names.

2. Line 34 I changed to my layer name.

CiaraMarleneKeenan_1-1703183107803.png

Thank you again 😊

 

0 Kudos
JuliaLenhardt
Emerging Contributor

This is old and solved, but I thought I would share this script as well for the label issue. In this script, for any label greater than 10 characters in length, the label gets split up based on a space that is closest to the middle of the string. For example, if the label is "Museum of Science", it finds the middle of the string (the letter "f" is in the exact middle), then finds the closest possible space (the one right after "of") and splits the string using a carriage return, to be:
Museum of
Science

// 1. Grab the raw label text from the feature
var txt = $feature.Label;

// If the label is empty, null, or short, just return it as-is
if (IsEmpty(txt) || Count(txt) <= 10) {
    return txt;
}

var textLength = Count(txt);
var targetIndex = textLength / 2; // The ideal halfway point

var closestSpaceIndex = -1;
var minDistance = textLength; // Start with the maximum possible distance

// 2. Loop through the string to find the space closest to the center
for (var i = 0; i < textLength; i++) {
    if (Mid(txt, i, 1) == " ") {
        var currentDistance = Abs(i - targetIndex);
       
        // If this space is closer to the center than the last one we found, track it
        if (currentDistance < minDistance) {
            minDistance = currentDistance;
            closestSpaceIndex = i;
        }
    }
}

// 3. Split the text at the closest space if one was found
if (closestSpaceIndex != -1) {
    var firstLine = Left(txt, closestSpaceIndex);
    // Grab everything after the space
    var secondLine = Right(txt, textLength - closestSpaceIndex - 1);
   
    // TextFormatting.NewLine forces a clean multi-line break in ArcGIS map rendering
    return firstLine + TextFormatting.NewLine + secondLine;
}

// Fallback: Return original text if no spaces were found
return txt;

 

0 Kudos