Add hyperlink to Customer Entry to open Google Earth

Low-coder here… I’m trying to add a hyperlink to Customer Entry (and Tracker) to open Google Earth to the customer’s address.

I’ve found Jose’s tutorial here - Add a Link Label to a Form (Email Link) - YouTube

I’m getting the following two compile errors. Is it something I messed up, or is because we’re on Kinetic 2021.2.5, and Jose’s tutorial from 2012 is literally in 4th grade now!).

Other than re-naming lblEmail’s to lblGoogleEarth, the rest should be typed verbatim (if I didn’t typo something).

The goal is to have the hyperlink be a string with the address formatted like:
https://earth.google.com/web/search/1395+John+Fitch+Blvd,+South+Windsor,+CT,+06074,+USA, and when it’s clicked, it opens Google Earth

(even better would be if I can figure out how to open Google Earth Pro with our pin layer on it).

I’m sure Google Earth has an API.
You should probably just embed that shit. :smiley:

Do It Episode 3 GIF by Star Wars

2 Likes

Peeping his video, you don’t need these prefixes:

image

Also… Epicor 9 :face_vomiting:

1 Like

And… I’ve been doing this for too long… clearly.

Epicor.Mfg.UI.Framework (E9) → Ice.Lib.Framework (E10+)

1 Like

Whoa, didn’t realize that was E9! It still looked like the ‘modern’ cough UI…

Sweet! Thanks Hannah. That takes care of the first error. I still get:

Error: CS0102 - line 36 (2654) - The type 'Script' already contains a definition for 'lblGoogleEarth'

Is that because I actually have a label that I created called ‘lblGoogleEarth’ using the toolbox?

Teach us how to embed that :poop: and I will! :slight_smile: We’re a long ways from Kineticizing the Customer Entry UI, but I’d love to learn and add it to the bag of tricks.

What’s the line of code look like?
If it’s Script.lblGoogleEarth change it to this.lblGoogleEarth.
Although… what are you even doing with the label?

this.lblGoogleEarth should work, but if not, do:
EpiLabel gEarthLbl = (EpiLabel)csm.GetNativeControlReference("The GUID for the label");
then do what you need to do with gEarthLbl.

I can’t read apparently, lol.
Yes–if you’re defining LinkLabel lblGoogleEarth AND you have a control named the same in properties, it’s gonna choke.

OK, getting closer! Thanks Hannah! Got the code to compile by deleting the label I created, following instructions more closely (to copy the group ‘type’ from the properties page, since it changed between versions), and fixed another error (typo, had an extra period).

Now, when I click the button (I closed Cust Maint and re-opened it first), I get an ‘Object reference not set to an instance of an object’ error (related to ‘Method: lblGoogleEarth_LinkClicked’).

I figure I should first hard code a URL in there to first test it. How?

image

These seem like the relevant parts, so I changed Jose’s email example from “EmailAddress” or (“mailto:” + target ) to a URL string here:

	private void lblGoogleEarth_LinkClicked(object Sender, LinkLabelLinkClickedEventArgs e)
	{
		String target = e.Link.LinkData.ToString();
		System.Diagnostics.Process.Start("https://earth.google.com/web/search/1395+John+Fitch+Boulevard,+South+Windsor,+CT");
	}

And here:

if(lblGoogleEarth.Links.Count>0)
				lblGoogleEarth.Links[0].LinkData= view.dataView[view.Row]["https://earth.google.com/web/search/1395+John+Fitch+Boulevard,+South+Windsor,+CT,+USA"].ToString();
			else
				lblGoogleEarth.Links.Add(0,lblGoogleEarth.Text.Length,view.dataView[view.Row]["https://earth.google.com/web/search/1395+John+Fitch+Boulevard,+South+Windsor,+CT,+USA"].ToString());
Application Error

Exception caught in: App.CustomerEntry.CustomerEntryForm.EP.ESAPCO.Customization.CustomerEntry_ALL_CBS.CustomCode.8

Error Detail 
============
Message: Object reference not set to an instance of an object.
Program: App.CustomerEntry.CustomerEntryForm.EP.ESAPCO.Customization.CustomerEntry_ALL_CBS.CustomCode.8.dll
Method: lblGoogleEarth_LinkClicked

Client Stack Trace 
==================
   at Script.lblGoogleEarth_LinkClicked(Object Sender, LinkLabelLinkClickedEventArgs e)
   at System.Windows.Forms.LinkLabel.OnLinkClicked(LinkLabelLinkClickedEventArgs e)
   at System.Windows.Forms.LinkLabel.OnMouseUp(MouseEventArgs e)
   at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.Label.WndProc(Message& m)
   at System.Windows.Forms.LinkLabel.WndProc(Message& msg)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

Have you stepped through it in Visual Studio to see what specific line it’s choking on and what the data is up until that point?

Done! Thanks for your help, Hannah. I still need to pretty it up, though. I phoned a friend, since I hadn’t set up VS with Epicor yet (seems like it’ll be very useful. Need to find the forum post where one you magic coders demonstrates that). The object reference error came from not having the LinkData setup properly.

image

If this helps anyone else - Here are the code snippets & rough location within Customer Entry’s Script Editor:

	// Add Custom Module Level Variables Here **
	Ice.Lib.Framework.EpiGroupBox grp;
	LinkLabel lblGoogleEarth;
		// End Wizard Added Custom Method Calls

		//Get hold of the group box where we'd like to put the link.
		grp= (EpiGroupBox)csm.GetNativeControlReference("177bd076-5c00-4d5f-ba20-d43e2b11977e"); 
		SetUpLinkLabel();
	}

	public void SetUpLinkLabel()
	{
		lblGoogleEarth = new LinkLabel();
		lblGoogleEarth.Name="lblGoogleEarth";
		lblGoogleEarth.Location= new System.Drawing.Point(6, 79);
		lblGoogleEarth.Size = new System.Drawing.Size(114,20);
		lblGoogleEarth.Text="Google Earth";
		lblGoogleEarth.Links[0].LinkData = "https://earth.google.com/web/search/1395+John+Fitch+Boulevard,+South+Windsor,+CT";
		lblGoogleEarth.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(lblGoogleEarth_LinkClicked);
		lblGoogleEarth.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
		lblGoogleEarth.BackColor = System.Drawing.Color.FromArgb(202,219,239);
		grp.Controls.Add(lblGoogleEarth);
	}

	private void lblGoogleEarth_LinkClicked(object Sender, LinkLabelLinkClickedEventArgs e)
	{
		//String target = e.Link.LinkData.ToString();
		System.Diagnostics.Process.Start(e.Link.LinkData.ToString()); //"https://earth.google.com/web/search/1395+John+Fitch+Boulevard,+South+Windsor,+CT");
	}
		// End Custom Code Disposal
		lblGoogleEarth.LinkClicked -= new System.Windows.Forms.LinkLabelLinkClickedEventHandler(lblGoogleEarth_LinkClicked);
		lblGoogleEarth.Dispose();
		lblGoogleEarth=null;

Can the address string be shortened in the data view URL string by not needing to repeat “+view.dataView[args.Row]” before every variable? Seems like the following code could be cleaner.

	private void edvCustomer_EpiViewNotification(EpiDataView view, EpiNotifyArgs args)
	{
		// ** Argument Properties and Uses **
		// view.dataView[args.Row]["FieldName"]
		// args.Row, args.Column, args.Sender, args.NotifyType
		// NotifyType.Initialize, NotifyType.AddRow, NotifyType.DeleteRow, NotifyType.InitLastView, NotifyType.InitAndResetTreeNodes
		if ((args.NotifyType == EpiTransaction.NotifyType.Initialize))
		{
			if ((args.Row > -1))
			{
				lblGoogleEarth.Links[0].LinkData = "https://earth.google.com/web/search/" +view.dataView[args.Row]["Address1"] + ",+" +view.dataView[args.Row]["City"] + ",+" +view.dataView[args.Row]["State"] + ",+"+view.dataView[args.Row]["Country"];
			}
		}
	}
2 Likes

Kind of depends on what the purpose of you putting it in the EpiViewNotification.
If it needs to be there, there’s not much you can do, but you can pretty it up.

// Global Variable
private string baseURL = "https://earth.google.com/web/search/";


private void edvCustomer_EpiViewNotification(EpiDataView view, EpiNotifyArgs args)
{
	// ** Argument Properties and Uses **
	// view.dataView[args.Row]["FieldName"]
	// args.Row, args.Column, args.Sender, args.NotifyType
	// NotifyType.Initialize, NotifyType.AddRow, NotifyType.DeleteRow, NotifyType.InitLastView, NotifyType.InitAndResetTreeNodes
	if ((args.NotifyType == EpiTransaction.NotifyType.Initialize))
	{
		if ((args.Row > -1))
		{
			lblGoogleEarth.Links[0].LinkData = baseURL + 
											   view.dataView[args.Row]["Address1"] + ",+" + 
											   view.dataView[args.Row]["City"] + ",+" + 
											   view.dataView[args.Row]["State"] + ",+" + 
											   view.dataView[args.Row]["Country"];
		}
	}
}

If you can call that code at the time you click the link, you can do something like this:

// Global Variable
private string baseURL = "https://earth.google.com/web/search/";
private EpiDataView edvCust;

// Initialize Custom Code
edvCust = oTrans.Factory("Customer");

// Destroy Custom Code
edvCust = null;

private void lblGoogleEarth_LinkClicked(object Sender, LinkLabelLinkClickedEventArgs e)
{
	//String target = e.Link.LinkData.ToString();
	string link = baseURL + 
				  GetEdvData("Address1") + ",+" + 
				  GetEdvData("City") + ",+" + 
				  GetEdvData("State") + ",+" + 
				  GetEdvData("Country");
				  
	System.Diagnostics.Process.Start(link); //"https://earth.google.com/web/search/1395+John+Fitch+Boulevard,+South+Windsor,+CT");
}

private string GetEdvData(string _identifier)
{
	return edvCust.dataView[edvCust.Row][_identifier].ToString();
}
3 Likes