Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Westi on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Tagcloud

Status
Not open for further replies.

Olaf Doschke

Programmer
Oct 13, 2004
14,847
DE
Tags and tagclouds are all over the internet. They are so useful, even Microsoft has discovered tag clouds for themselves and made Tagspace (
The useful thing is, you can see several orders at a time, first tags are alphabetically ordered, then their importance is shown by there size. Something a simple list or a grid can only display once at a time by ordering. You can even add one more property by using the saturation of the tags and then could also use the color for another property.

I just played around with the idea and jsut used size and saturation to display Northwind customers in a way you may never have seen before:

Code:
Local lnMaxbrightness, lnMaxFontsize, lnMinFontsize, lcHTML, lnCol
lnMaxbrightness=200
lnMaxFontsize=49
lnMinFontsize=7

Close Databases All
Open Database Home()+"Samples\Northwind\Northwind.dbc"

Select;
   Customers.Companyname,;
   CustomerStats.nOrders,;
   Sum(Orderdetails.quantity * Orderdetails.unitprice * (1-Orderdetails.discount)) As nTotal,;
   (CustomerStats.dTo-CustomerStats.dFrom+1) As nDays;
From;
   Customers,orders,orderdetails,;
   (Select;
       Customerid,;
       Count(*) As nOrders,;
       Min(orderdate) As dFrom,;
       Max(orderdate) As dTo;
    From;
       Orders;
       Group By 1;
   ) As CustomerStats;
   Group By Companyname,nOrders,nDays;
   Order By Companyname;
Where Customers.Customerid = CustomerStats.Customerid;
   and Orders.Customerid = Customers.Customerid;
   and Orders.Orderid = Orderdetails.Orderid;
Into Cursor curCustomers nofilter

Select;
   Max(nTotal/nOrders) As nMaxAverageOrders,;
   Max(nTotal/nDays) As nMaxAverageTotal;
From curCustomers;
Into Cursor curMax

lcHTML = ""
Select curCustomers
Scan
   lnCol = Int(Mton(curCustomers.nTotal/curCustomers.nDays/curMax.nMaxAverageTotal*lnMaxbrightness))
   TEXT to lcHTML additive Textmerge Noshow
   <a style="font-size:<<Int(Mton(curCustomers.nTotal/curCustomers.nOrders/curMax.nMaxAverageOrders*(lnMaxFontsize-lnMinfontsize)+lnMinfontsize+.5))>>pt;
   color:#<<Right(Transform(65793*(lnMaxBrightness-lnCol),"@0"),6)>>;"><<curCustomers.Companyname>></a>
   ENDTEXT
EndScan

Local lcFile
lcFile = Addbs(GetEnv("TEMP"))+Sys(2015)+".html"
Strtofile("<html><body>"+lcHTML+"</body></html>",lcFile)
o = CreateObject("internetexplorer.application")
o.navigate2("file://"+lcFile)
o.Visible = .T.

Bye, Olaf.
 
That's pretty cool. I don't know if YAG visits this site, but you may want to shoot him your code (yag@microsoft.com). He's an Architect on the communities team that did TagSpace.

Craig Berntson
MCSD, Visual FoxPro MVP, Author, CrysDev: A Developer's Guide to Integrating Crystal Reports&quot;
 
Hello Craig,

thanks, While Microsofts tag cloud does only make use of few font sizes, it has other features way ahead. I just wondered how to do it, but it's simply: let the browser render the tags, so you won't need to think about spacing etc.

Besides that there are already relly cool features in tagspace. You see those little [+] like in a treeview control? If you click on it you see the items tagged with that tag, just like clicking on the tag itself, at first not different. But if you click on a [+] of a second tag, you get a filter of items tagged with both tags....call it incremental filtering.

I'll give YAG feedback on this. Psst, at the summit I accidently went to the community services group breakfast with YAG showing something about what is now out as a beta.
I'm looking forward to see more of it coming.

Bye, Olaf.
 
Olaf,

Very cool. Thanks for the runnable example.

boyd.gif

SweetPotato Software Website
My Blog
 
Olaf: Real Cool.

Shamelessly plagiarizing your code and idea, I fooled around with it and come up with a way to display a “Tag cloud” in a form. Though somehow, I know its gathering popularity, I am not sold on the idea of tag clouds nor tags. IMO they are too chaotic and a PIA to display meaningful information.
But here is some code on how it could be done in VFP: this displays a tag cloud in a form and when you “hover “your mouse over the label, the caption changes to the Total Purchase amount. (“nTotal” in Olafs example)
Need a subclass of a Label first, then create the form.

Code:
**************************************************
*-- Class:        tool_label (c:\imaginecorp\libraries\tagcloud.vcx)
*-- ParentClass:  label
*-- BaseClass:    label
*-- Time Stamp:   04/23/07 08:20:06 PM
*
DEFINE CLASS tool_label AS label


	AutoSize = .T.
	BackStyle = 0
	Caption = "Label1"
	Height = 17
	Width = 40
	Name = "tool_label"


	PROCEDURE MouseEnter
		Lparameters nButton, nShift, nXCoord, nYCoord
		this.Caption = "Purchases: "+ALLTRIM(Transform(This.totalorders, "@R$ ###,###,###.##"))
		this.ForeColor = RGB(0,0,0)
	ENDPROC


	PROCEDURE MouseLeave
		LPARAMETERS nButton, nShift, nXCoord, nYCoord
		this.ForeColor = this.oldcolor
		this.Caption = this.cCaption
	ENDPROC


	PROCEDURE Init
		With This
			.AddProperty("totalorders",0)
			.AddProperty("cCaption","")
			.AddProperty("OldColor",0)
		Endwith
	ENDPROC


ENDDEFINE
*
*-- EndDefine: tool_label
**************************************************

Now create the form: Needs fine tuning

Code:
**************************************************
*-- Form:         form1 (c:\imaginecorp\form3.scx)
*-- ParentClass:  form
*-- BaseClass:    form
*-- Time Stamp:   04/23/07 08:18:01 PM
*
DEFINE CLASS form1 AS form


	Top = 14
	Left = 27
	Height = 400
	Width = 600
	ScrollBars = 2
	DoCreate = .T.
	Caption = "Form1"
	BackColor = RGB(242,242,242)
	Name = "Form1"


	PROCEDURE Init
*****Change the following to where you
*****saved the Label class		
Set Classlib To c:\imaginecorp\libraries\tagcloud
***************************************
		Local lnMaxFontsize, lnMinFontsize ,lnMaxbrightness
		lnMaxbrightness=200
		lnMaxFontsize=49
		lnMinFontsize=7
		Close Databases All
		Open Database Home()+"Samples\Northwind\Northwind.dbc"

		Select;
			Customers.Companyname,CustomerStats.nOrders,;
			Sum(Orderdetails.quantity * Orderdetails.unitprice * (1-Orderdetails.discount)) As nTotal,;
			(CustomerStats.dTo-CustomerStats.dFrom+1) As nDays;
			From;
			Customers,orders,Orderdetails,(Select Customerid,;
			Count(*) As nOrders,Min(orderdate) As dFrom,Max(orderdate) As dTo;
			FROM orders ;
			Group By 1 ) As CustomerStats;
			Group By Companyname,nOrders,nDays;
			Order By Companyname;
			Where Customers.Customerid = CustomerStats.Customerid;
			and orders.Customerid = Customers.Customerid;
			and orders.Orderid = Orderdetails.Orderid;
			Into Cursor curCustomers nofilter

		Select;
			Max(nTotal/nOrders) As nMaxAverageOrders,;
			Max(nTotal/nDays) As nMaxAverageTotal;
			From curCustomers;
			Into Cursor curMax

		Select curCustomers
		Store 0 To nRecno, nLeft, nwidth, nheight, nFontHeight,nwidth,nTop
		nTop = 33
		With This
			Scan
				nRecno = nRecno + 1
				clabel = "label"+Transform(nRecno)
				nLeft = nLeft + nwidth  + 10
				nFontSize = Ceiling(Int(Mton(curCustomers.nTotal/curCustomers.nOrders/;
					curMax.nMaxAverageOrders*(lnMaxFontsize-lnMinFontsize)+lnMinFontsize+.5)))
				nFontHeight = Fontmetric(1,"Arial",nFontSize)
				nwidth = Ceiling((Len(Alltrim(curCustomers.Companyname)) * Fontmetric(6,"Arial",nFontSize))+ ;
					(Fontmetric(6,"Arial",nFontSize)*2))
				lnCol = Int(Mton(curCustomers.nTotal/curCustomers.nDays/;
					curMax.nMaxAverageTotal*lnMaxbrightness))
				If (nLeft+nwidth) > (.Width - 10)
					nLeft = 3
					nTop = nTop + 49
					nheight = nheight + nTop + 52
					.Height = nheight
				Endif
				.AddObject(clabel,"tool_label")
				oCont = Evaluate("this."+clabel)
				With oCont
					.Top = (nTop - nFontHeight)+1
					.Caption = Alltrim(curCustomers.Companyname)
					.cCaption = .Caption
					.totalorders = curCustomers.nTotal
					.ForeColor = 65793*(lnMaxbrightness-lnCol)
					.OldColor = .ForeColor
					.FontSize = nFontSize
					.Left = nLeft
					.Visible = .T.
				Endwith
			Endscan
			.Height = 400
			.Width = 600
		Endwith
		Close All
	ENDPROC


ENDDEFINE
*
*-- EndDefine: form1
**************************************************
The possibilities are endless, you could hide a Editbox behind the label (visible = .f.) this could hold all the transaction detail. Mouse Enter would make the label invisible and the editbox visible and mouse leave vice versa. Or display another form with the transaction details when label is clicked.

Again; I did not spend too much time on this and it needs prettying up.
 
Hi Imaginecorp,

nice. I'd rather go for a webbrowser control on a form, but it's of course a nice thing to have this with native controls. Next thing would be to rerender the cloud when resizing the form, especially adapting to the width of course. Nice idea to change the label on mouseover.

I started with printing to the _screen (simply _screen.forecolor=..., _screen.fontsize=..., ??companyname), but the line feeds where done with the last fontsize so I was overwriting previous tags in most cases of course.

You may like the tag clouds at delicious better ( the have a fixed line height. So maybe it's the way to go to not have that much diversity in font sizes. I like how you get focused on the most relevant records with tag clouds. I will add DHTML features and on mouseover resize a tag, fade to dark blue for example to have equal readability. Logarithms of scales is also a topic to adress, if a scale gets ver large. That could be done with the total purchase amount.

Bye, Olaf.
 
Hello Olaf:
Congratulations on the MVP.
Regarding a web browser, adding “labels” that do something is beyond the level of my expertise. I did manage to get the labels to line up, though not hundred percent. Fooling around with this has got me thinking of incorporating it in our app. We have an executive dashboard and the tag cloud would be an ideal candidate as opposed to a grid. I now create it in a container with a Slider control in a form. Like del.icio.us I have also added a “display by” feature. We do have a Resize Class on our forms, which only gets activated if the user wants it, which seems to handle the resize of the labels without a problem.
The only problem seems to be the setting of the Font size. Especially if the total purchases for a few customers were only a 100, another few a thousand and majority in the hundred thousand and the max is a million. Thought about colors for different amount levels, but that defeats the use of size and gives the appearance an amateurish look. Will work on it next week.
 
Hi Imaginecorp,

thanks. As I announced I made some improvements on my tag coud code. First made it a bit more readable and imprived variable naming.

I stayed with html and a browser. I introduce a bit of CSS, added a title tag, which displays average order amount and average daily cashflow and used a bit javascript to resize links on mouseenter and set their size back at mouseleave. The browser rerenders that with ease. I made all lines eqully high, aligned the tags on the baseline and changed background to black and colored the company names with alternating colors in blueish and greenish, which makes it better readable.

On vista you need to allow the javascript on the page to run first. Next step would be putting the html into a webbrowser control on a vfp form and handle events with vfp instead of javascript. Also an issue remains: When you point to a companyname on the right border due to font resizing it may be rendered to the next line and therfore mouseleave is triggerd instantly. I think there is no easy way out of this, but I'll try.

Code:
Local lnMinBrightness, lnMaxbrightness
Local lnMaxFontsize, lnMinFontsize
Local lnColorEmphasis, lnFontsizeEmphasis
Local lcHTML, lnCount

lnMinBrightness=20
lnMaxbrightness=100

lnMaxFontsize=32
lnMinFontsize=7

Close Databases All
Open Database Home()+"Samples\Northwind\Northwind.dbc"

Select;
   Customers.Companyname,;
   CustomerStats.nOrders,;
   Sum(Orderdetails.quantity * Orderdetails.unitprice * (1-Orderdetails.discount)) As nTotal,;
   (CustomerStats.dTo-CustomerStats.dFrom+1) As nDays;
From;
   Customers,orders,orderdetails,;
   (Select;
       Customerid,;
       Count(*) As nOrders,;
       Min(orderdate) As dFrom,;
       Max(orderdate) As dTo;
    From;
       Orders;
       Group By 1;
   ) As CustomerStats;
   Group By Companyname,nOrders,nDays;
   Order By Companyname;
Where Customers.Customerid = CustomerStats.Customerid;
   and Orders.Customerid = Customers.Customerid;
   and Orders.Orderid = Orderdetails.Orderid;
Into Cursor curCustomers nofilter

Select;
   Max(nTotal/nOrders) As nMaxAverageOrders,;
   Max(nTotal/nDays) As nMaxAverageTotal;
From curCustomers;
Into Cursor curMax

TEXT to lcHTML Textmerge Noshow
<html><style type="text/css">
.tag {font-family:Arial,Helvetica; line-height:<<lnMaxFontsize+2>>pt; vertical-align:baseline; }
</style>
<script language="jscript">
function resizeenter(cId) {document.getElementById(cId).style.fontSize="<<lnMaxFontsize>>pt";}
function resizeleave(cId,nSize) {document.getElementById(cId).style.fontSize=nSize+"pt";}
</script>
<body bgcolor="#0000000">
ENDTEXT

*=<<lnMaxFontsize>>pt;

lnCount=0
Select curCustomers
Scan
   lnCount = lnCount + 1
   If lnCount%2=0
      lnR=.5
      lnG=.5
      lnB=1
   Else
      lnR=.5
      lnG=1
      lnB=.5
   Endif

   lnColorEmphasis    = Mton(curCustomers.nTotal/curCustomers.nDays/curMax.nMaxAverageTotal)
   lnFontsizeEmphasis = Mton(curCustomers.nTotal/curCustomers.nOrders/curMax.nMaxAverageOrders)
   TEXT to lcHTML Additive Textmerge Noshow
<a id="<<lnCount>>" class="tag" originalfontsize="8pt" _nocrlf_
style="font-size:<<Int(lnFontsizeEmphasis*(lnMaxFontsize-lnMinfontsize)+lnMinfontsize+.5))>>pt; _nocrlf_
color:rgb(_nocrlf_
<<Int((lnColorEmphasis*(lnMaxbrightness-lnMinBrightness)+lnMinBrightness)*lnR+.5)>>%,_nocrlf_
<<Int((lnColorEmphasis*(lnMaxbrightness-lnMinBrightness)+lnMinBrightness)*lnG+.5)>>%,_nocrlf_
<<Int((lnColorEmphasis*(lnMaxbrightness-lnMinBrightness)+lnMinBrightness)*lnB+.5)>>%)_nocrlf_
;" title="average $<<curCustomers.nTotal/curCustomers.nOrders>> per order
average cashflow $<<curCustomers.nTotal/curCustomers.nDays>> per day" _nocrlf_
onmouseenter="javascript:resizeenter('<<lnCount>>');" _nocrlf_
onmouseleave="javascript:resizeleave('<<lnCount>>',_nocrlf_
<<Int(lnFontsizeEmphasis*(lnMaxFontsize-lnMinfontsize)+lnMinfontsize+.5))>>);">_nocrlf_
<<curCustomers.Companyname>></a>
   ENDTEXT
Endscan

lcHTML = Strtran(lcHTML,"_nocrlf_"+Chr(13)+Chr(10)," ")

Local lcFile
lcFile = Addbs(Getenv("TEMP"))+Sys(2015)+".html"
Strtofile(lcHTML+"</body></html>",lcFile)
o = Createobject("internetexplorer.application")
o.navigate2("file://"+lcFile)
o.Visible = .T.

Bye, Olaf.
 
Olaf:

WOW! Mondo Cool. Love the way the fonts change size... Could probably create the browser control in a container with a slider on a page frame… That is what I was thinking of. As stated earlier the tagcloud will be part of an Executive Dashboard which has multiple pages, also I need to put in at least 2 levels of drill down functionality…really do not want to go to another page for details… Tool tips may not be enough…
Excellent work…
 
Hi Imaginecorp,

Now, here's a version with a webbrowser control using your Orderdetails form:

Code:
oForm = Createobject("tagcloudform")
oForm.Show(1)

Define Class tagcloudform As Form
   Top = 0
   Left = 0
   Height = 768
   Width = 1236
   DoCreate = .T.
   Caption = "Customer Tagcloud"
   oLinkhandler = .Null.

   Add Object olecontrol1 As cWeb With ;
      Top = 12, ;
      Left = 12, ;
      Height = 744, ;
      Width = 1212

   Procedure Init()
      Local lnMinBrightness, lnMaxbrightness
      Local lnMaxFontsize, lnMinFontsize
      Local lnColorEmphasis, lnFontsizeEmphasis
      Local lcHTML, lnCount

      lnMinBrightness=80
      lnMaxbrightness=200

      lnMaxFontsize=32
      lnMinFontsize=7

      Close Databases All
      Open Database Home()+"Samples\Northwind\Northwind.dbc"

      Select;
         Customers.Customerid,;
         Customers.Companyname,;
         CustomerStats.nOrders,;
         Sum(Orderdetails.quantity * Orderdetails.unitprice * (1-Orderdetails.discount)) As nTotal,;
         (CustomerStats.dTo-CustomerStats.dFrom+1) As nDays,;
         Cast(0 As I) As nFontsize,;
         Cast("" As C(20)) As cColor;
         From;
         Customers, orders, Orderdetails,;
         (Select;
         Customerid,;
         Count(*) As nOrders,;
         Min(orderdate) As dFrom,;
         Max(orderdate) As dTo;
         From;
         orders;
         Group By 1;
         ) As CustomerStats;
         Group By 1,Companyname,nOrders,nDays;
         Order By Companyname;
         Where Customers.Customerid = CustomerStats.Customerid;
         and orders.Customerid = Customers.Customerid;
         and orders.Orderid = Orderdetails.Orderid;
         Into Cursor curCustomers Readwrite

      Index On Customerid Tag xCustid

      Select;
         Max(nTotal/nOrders) As nMaxAverageOrders,;
         Max(nTotal/nDays) As nMaxAverageTotal;
         From curCustomers;
         Into Cursor curMax

      TEXT to lcHTML Textmerge Noshow
<html><style type="text/css">
a:link {text-decoration:none;}
a:visited {text-decoration:none;}
a:focus { text-decoration:underline; color: white;}
a:hover { text-decoration:underline; color: white;}
a:active { text-decoration:none; }
.tag {font-family:Arial,Helvetica; line-height:<<lnMaxFontsize+2>>pt; vertical-align:baseline; }
</style>
<body bgcolor="#0000000">
      ENDTEXT

      lnCount = 0
      Select curCustomers
      Scan
         lnCount = lnCount + 1
         If lnCount%2=0
            lnR=.5
            lnG=.5
            lnB=1
         Else
            lnR=.5
            lnG=1
            lnB=.5
         Endif

         lnColorEmphasis    = Mton(curCustomers.nTotal/curCustomers.nDays/curMax.nMaxAverageTotal)
         lnFontsizeEmphasis = Mton(curCustomers.nTotal/curCustomers.nOrders/curMax.nMaxAverageOrders)
         lnBrightness = lnColorEmphasis*(lnMaxbrightness-lnMinBrightness)+lnMinBrightness

         Replace nFontsize With Int(lnFontsizeEmphasis*(lnMaxFontsize-lnMinFontsize)+lnMinFontsize+.5),;
            cColor With "rgb("+Transform(Int(lnBrightness*lnR+.5))+","+Transform(Int(lnBrightness*lnG+.5));
            +","+Transform(Int(lnBrightness*lnB+.5))+")" In "curCustomers"

         TEXT to lcHTML Additive Textmerge Noshow
<a id="<<curCustomers.Customerid>>" class="tag" _nocrlf_
style="font-size:<<curCustomers.nFontsize>>pt; _nocrlf_
color:<<curCustomers.cColor>>;" title="average $<<curCustomers.nTotal/curCustomers.nOrders>> per order
average cashflow $<<curCustomers.nTotal/curCustomers.nDays>> per day" href="vfp:<<curCustomers.Customerid>>">_nocrlf_
<<curCustomers.Companyname>></a>
         ENDTEXT
      Endscan

      lcHTML = Strtran(lcHTML,"_nocrlf_"+Chr(13)+Chr(10)," ")

      Local lcFile
      lcFile = Addbs(Getenv("TEMP"))+Sys(2015)+".html"
      Strtofile(lcHTML+"</body></html>",lcFile)


      Thisform.olecontrol1.Object.navigate2("file://"+lcFile)
      Do While Thisform.olecontrol1.Object.readystate#4
         DoEvents
      Enddo

      Thisform.oLinkhandler = Createobject("LinkHandler",lnMaxFontsize)
      Thisform.oLinkhandler.BindHTMLDocument(Thisform.olecontrol1.Object.Document)
   Endproc
Enddefine

Define Class cWeb As OleControl
   OleClass="shell.explorer.2"

   Procedure Refresh()
      Nodefault
   Endproc

   Procedure BeforeNavigate2()
      Lparameters pdisp, url, Flags, targetframename, postdata, headers, Cancel

      If Left(url,4)=="vfp:"
         Local lcCustomerID, loForm
         lcCustomerID = Substr(url,5)
         loForm = Createobject("cloudorders",lcCustomerID)
         loForm.Show(1)
         Cancel = .T.
      Endif
   Endproc
Enddefine

Define Class cloudorders As Form
   Top = 48
   Left = 58
   Height = 235
   Width = 478
   DoCreate = .T.
   BorderStyle = 2
   Caption = "Form1"
   Name = "cloudorders"


   Add Object grid1 As Grid With ;
      ColumnCount = 6, ;
      DeleteMark = .F., ;
      GridLines = 3, ;
      Height = 200, ;
      Left = 5, ;
      ReadOnly = .T., ;
      RecordMark = .T., ;
      RecordSource = ['" "'], ;
      ScrollBars = 2, ;
      Top = 5, ;
      Width = 467, ;
      GridLineColor = Rgb(192,192,192), ;
      HighlightStyle = 2, ;
      AllowCellSelection = .F., ;
      Name = "Grid1", ;
      Column1.ControlSource = "", ;
      Column1.Width = 70, ;
      Column1.ReadOnly = .T., ;
      Column1.Name = "Column1", ;
      Column2.ColumnOrder = 3, ;
      Column2.ControlSource = "", ;
      Column2.Width = 70, ;
      Column2.ReadOnly = .T., ;
      Column2.Name = "Column2", ;
      Column3.ColumnOrder = 2, ;
      Column3.ControlSource = "", ;
      Column3.Width = 70, ;
      Column3.ReadOnly = .T., ;
      Column3.Name = "Column3", ;
      Column4.ControlSource = "", ;
      Column4.Width = 70, ;
      Column4.ReadOnly = .T., ;
      Column4.Name = "Column4", ;
      Column5.ControlSource = "", ;
      Column5.Width = 75, ;
      Column5.ReadOnly = .T., ;
      Column5.Format = "R$", ;
      Column5.InputMask = "###,###.##", ;
      Column5.Name = "Column5", ;
      Column6.ControlSource = "", ;
      Column6.Width = 75, ;
      Column6.ReadOnly = .T., ;
      Column6.Format = "R$", ;
      Column6.InputMask = "###,###.##", ;
      Column6.Name = "Column6"

   Add Object text1 As TextBox With ;
      Format = "R$", ;
      Height = 23, ;
      InputMask = "###,###,###.##", ;
      Left = 322, ;
      ReadOnly = .T., ;
      TabStop = .F., ;
      Top = 207, ;
      Width = 130, ;
      Name = "Text1"


   Add Object label1 As Label With ;
      AutoSize = .T., ;
      BackStyle = 0, ;
      Caption = "Total Purchases Todate:", ;
      Height = 17, ;
      Left = 170, ;
      Top = 211, ;
      Width = 136, ;
      Name = "Label1"

   Procedure Deactivate
      This.Release
   Endproc

   Procedure Init
      Lparameters pCustId
      Set Talk Off
      Select Customers.Companyname,orders.Orderid,orders.orderdate,;
         orders.requireddate,orders.shippeddate,orders.freight,Sum((Orderdetails.unitprice*Orderdetails.quantity)-;
         ((Orderdetails.unitprice*Orderdetails.quantity)*Orderdetails.discount)) As totalcost ;
         FROM Customers,orders,Orderdetails ;
         WHERE Customers.Customerid = pCustId ;
         AND Customers.Customerid = orders.Customerid ;
         AND orders.Orderid = Orderdetails.Orderid ;
         GROUP By 1,2,3,4,5,6 ;
         ORDER By 3,2 ;
         INTO Cursor custcursor

      This.Caption = Alltrim(custcursor.Companyname)+"'s Transcations..."

      Calculate Sum(totalcost+freight) To This.text1.Value
      With This.grid1
         .RecordSource = "custcursor"
         .Column1.ControlSource = "custcursor.orderid"
         .Column2.ControlSource = "custcursor.orderdate"
         .Column3.ControlSource = "custcursor.requireddate"
         .Column4.ControlSource = "custcursor.shippeddate"
         .Column5.ControlSource = "custcursor.freight"
         .Column6.ControlSource = "custcursor.totalcost"

         .Column1.header1.Caption ="Order ID"
         .Column2.header1.Caption = "Req. Date"
         .Column3.header1.Caption = "Order Date"
         .Column4.header1.Caption = "Ship Date"
         .Column5.header1.Caption = "Freight"
         .Column6.header1.Caption = "Cost"

         .Refresh
         Go Top
      Endwith

   Endproc
Enddefine


Define Class LinkHandler As vfpHTMLElementEvents
   oDoc = .Null.
   cMaxFontsize = ""

   Procedure Init()
      Lparameters tnMaxFontsize
      This.cMaxFontsize = Transform(tnMaxFontsize)+"pt"
   Endproc

   Procedure BindHTMLDocument()
      Lparameters toDoc
      If Vartype(toDoc)="O"
         This.oDoc = toDoc
         Eventhandler(This.oDoc,This)
      Endif
   Endproc

   Procedure UnBindHTMLDocument()
      If Vartype(This.oDoc)="O"
         Eventhandler(This.oDoc,This,.T.)
         This.oDoc = .Null.
      Endif
   Endproc

   Procedure HTMLElementEvents_onmouseover() As VOID
      Local loLink
      loLink = This.oDoc.parentWindow.Event.srcElement
      loLink.Style.FontSize = This.cMaxFontsize
      loLink.Style.Color = ""
   Endproc

   Procedure HTMLElementEvents_onmouseout() As VOID
      Local loLink
      loLink = This.oDoc.parentWindow.Event.srcElement
      If Seek(loLink.Id,"curCustomers","xCustid")
         loLink.Style.FontSize = Transform(curCustomers.nFontsize)+"pt"
         loLink.Style.Color = Alltrim(curCustomers.cColor)
      Endif
   Endproc
Enddefine

Define Class vfpHTMLElementEvents1 As Custom

   Implements HTMLElementEvents In "c:\windows\system32\mshtml.tlb"

   Procedure HTMLElementEvents_onhelp() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onclick() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_ondblclick() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onkeypress() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onkeydown() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onkeyup() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onmouseout() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onmouseover() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onmousemove() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onmousedown() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onmouseup() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onselectstart() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onfilterchange() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_ondragstart() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onbeforeupdate() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onafterupdate() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onerrorupdate() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onrowexit() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onrowenter() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_ondatasetchanged() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_ondataavailable() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_ondatasetcomplete() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onlosecapture() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onpropertychange() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onscroll() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onfocus() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onblur() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onresize() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_ondrag() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_ondragend() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_ondragenter() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_ondragover() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_ondragleave() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_ondrop() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onbeforecut() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_oncut() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onbeforecopy() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_oncopy() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onbeforepaste() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onpaste() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_oncontextmenu() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onrowsdelete() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onrowsinserted() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_oncellchange() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onreadystatechange() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onbeforeeditfocus() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onlayoutcomplete() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onpage() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onbeforedeactivate() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onbeforeactivate() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onmove() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_oncontrolselect() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onmovestart() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onmoveend() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onresizestart() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onresizeend() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onmouseenter() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onmouseleave() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onmousewheel() As LOGICAL
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onactivate() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_ondeactivate() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onfocusin() As VOID
      * add user code here
   Endproc

   Procedure HTMLElementEvents_onfocusout() As VOID
      * add user code here
   Endproc

Enddefine
 
Olaf:

This is WAY beyond my level of expertise... Will try it out later. Thanks
 
finally to make this code friendly for use with older versions, you can decompose the SQL to:

Code:
Select;
   Customerid,;
   Count(*) As nOrders,;
   Min(orderdate) As dFrom,;
   Max(orderdate) As dTo;
From;
   Orders;
Group By 1;
Into Cursor CustomerStats Nofilter

Select;
   Customers.Customerid,;
   Customers.Companyname,;
   CustomerStats.nOrders,;
   Sum(Orderdetails.quantity * Orderdetails.unitprice * (1-Orderdetails.discount)) As nTotal,;
   (CustomerStats.dTo-CustomerStats.dFrom+1) As nDays,;
   (000) As nFontsize,;
   Space(20) As cColor;
From;
   Customers, orders, Orderdetails, CustomerStats;
Group By 1,Companyname,nOrders,nDays;
Order By Companyname;
Where Customers.Customerid = CustomerStats.Customerid;
   and orders.Customerid = Customers.Customerid;
   and orders.Orderid = Orderdetails.Orderid;
Into Cursor curCustomers Readwrite

Maybe make the CustomerStats cursor readwrite and create an index on CustomerID. I wouldn't focus on getting this into one single SQL.

Bye, Olaf.
 
Thanks, Olaf. I'll try it later.
 
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Sponsor

Back
Top