This is a follow-up question after a comment left on my last question/answer.
I have this code a HTML table but the first column has no name, which means the headings don't line up properly. This is because I'm using this syntax to identify even/odd rows - cast((select ROW_NUMBER() over(order by id) % 2 as 'td',
How can I set the heading for the first column?
set #tableHTML = '<html><head><style>' +
'td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:11pt;} ' +
'</style></head><body>'
+ '<div style="margin-top:20px; margin-left:5px; margin-bottom:15px; font-weight:bold; font-size:1.3em; font-family:tahoma;">' +
#textTitle + '</div>'
+ '<div style="margin-left:50px; font-family:tahoma;"><table cellpadding=0 cellspacing=0 border=0>' +
'<tr bgcolor=#4b6c9e>'
+ '<td align=center><font face="calibri" color=White><b>Col1</b></font></td>'
+ '<td align=center><font face="calibri" color=White><b>Col2</b></font></td>'
+ '<td align=center><font face="calibri" color=White><b>Col3</b></font></td>'
+ '<td align=center><font face="calibri" color=White><b>Col4</b></font></td>'
+ '<td align=center><font face="calibri" color=White><b>Col5</b></font></td>'
+
'</tr>'
select #body =
cast((select ROW_NUMBER() over(order by id) % 2 as 'td',
'',
isnull(col1,'') as 'td',
'',
isnull(col2,'') as 'td',
'',
isnull(col3,'') as 'td',
'',
isnull(col4,'') as 'td',
'',
isnull(col5,'') as 'td'
from #tableUpdate
where notificationType = 'NEWDATE'
order by clname
for XML path('tr'), elements) as nvarchar(max))
select #tableHTML = #tableHTML + #body
+ '</table></div></body></html>'
Your HTML is stronger than mine, but this should work and allow you to insert your styling where appropriate (if still needed).
select #body =
cast((select ROW_NUMBER() over(order by id) % 2 as 'td',
'',
isnull(col1,'') as 'td',
'',
isnull(col2,'') as 'td',
'',
isnull(col3,'') as 'td',
'',
isnull(col4,'') as 'td',
'',
isnull(col5,'') as 'td'
from #tableUpdate
where notificationType = 'NEWDATE'
order by clname
for XML path('tr'), elements) as nvarchar(max))
set #tableHTML = '<html>
<body>
<header>
<H3>This would be your header... maybey #textTitle information?</H3>
<P>Insert some stuff here if you want</P>
</header>
<table border = 1>
<tr>
<th>IDCol</th>
<th>Col1</th>
<th>Col2</th>
<th>Col3/th>
<th>Col4</th>
<th>Col5</th>
</tr>'
select #tableHTML = #tableHTML + isnull(#body,'') + '</table></body></html>'
Related
SET #tableHTML =
N'<H1>Report Heading</H1>' +
N'<table border="1">' +
N'<th>Check Number</th>' +
N'<th>Last Operator Date</th>' +
N'<th>Last Timestamp</th>' +
N'<th>Run Date</th>' +
N'<th>Issued Check Number</th>' +
N'<th>Error Description</th>' +
'<tr>' +
CAST ( ( SELECT td = S.CHK_NUM, '',
td = S.LAST_OPER_ID, '',
td = S.LAST_TIMESTMP, '',
td = S.RUN_DT, '',
td = ISNULL(S.RE_ISSUE_CHK_NUM,-1), '',
td = ISNULL(S.ERR_DESC,'<null>'), ''
FROM STAGNG_CDDP_ERR_RCD S
FOR XML PATH('tr'), TYPE
) AS NVARCHAR(MAX) ) +
N'</table>' ;
PRINT #tableHTML
I want to count the resulting rows and assign it to a variable. How can that be achieved?
Just add a count query:
DECLARE #tableHTML NVARCHAR(MAX), #Count int;
SELECT #tableHTML =
N'<H1>Report Heading</H1>' +
N'<table border="1">' +
N'<th>Check Number</th>' +
N'<th>Last Operator Date</th>' +
N'<th>Last Timestamp</th>' +
N'<th>Run Date</th>' +
N'<th>Issued Check Number</th>' +
N'<th>Error Description</th>' +
'<tr>' +
CAST ( ( SELECT td = S.CHK_NUM, '',
td = S.LAST_OPER_ID, '',
td = S.LAST_TIMESTMP, '',
td = S.RUN_DT, '',
td = ISNULL(S.RE_ISSUE_CHK_NUM,-1), '',
td = ISNULL(S.ERR_DESC,'<null>'), ''
FROM STAGNG_CDDP_ERR_RCD S
FOR XML PATH('tr'), TYPE
) AS NVARCHAR(MAX) ) +
N'</table>'
, #Count = (SELECT COUNT(*) FROM STAGNG_CDDP_ERR_RCD);
PRINT #Count;
PRINT #tableHTML;
I am sending a HTML email that contains some rows from a table. I am using a temporary table #tableupdate which definitely has data in it when I run the script.
Everything runs fine and I get the email, it just has no content whatsoever. When I view the source of the email it's blank. Can anyone see where I have gone wrong?
To help diagnose the problem, I've been outputting the contents of the variable containing all the HTML in it at various points and it seems to be empty after this part:
select #tableHTML = #tableHTML + #body
+ '</table></div></body></html>'
#body doesn't seem to populate at all. I'm just not sure what to change to make it work.
The relevant piece of code, including comments to show where the data disappears:
select * from #tableupdate --rows are returned
declare #emailSubject varchar(100),
#textTitle varchar(100),
#tableHTML nvarchar(max)
select #textTitle = 'Test table'
set #tableHTML = '<html><head><style>' +
'td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:11pt;} ' +
'</style></head><body>'
+ '<div style="margin-top:20px; margin-left:5px; margin-bottom:15px; font-weight:bold; font-size:1.3em; font-family:tahoma;">' +
#textTitle + '</div>'
+ '<div style="margin-left:50px; font-family:tahoma;"><table cellpadding=0 cellspacing=0 border=0>' +
'<tr bgcolor=#4b6c9e>'
+ '<td align=center><font face="calibri" color=White><b>Col1</b></font></td>'
+ '<td align=center><font face="calibri" color=White><b>Col2</b></font></td>'
+ '<td align=center><font face="calibri" color=White><b>Col3</b></font></td>'
+ '<td align=center><font face="calibri" color=White><b>Col4</b></font></td>'
+ '<td align=center><font face="calibri" color=White><b>Col5</b></font></td>'
+
'</tr>'
select #tablehtml --has the correct value at this point
select #body =
(
select ROW_NUMBER() over(order by id) % 2 as TRRow,
td = col1,
td = col2,
td = col3,
td = col4,
td = col5
from #tableUpdate
where notificationType = 'NEWDATE'
order by clname
for XML raw('tr'), elements
)
select #body --empty?!
set #body = REPLACE(#body, '<td>', '<td align=center><font face="tahoma">')
set #body = REPLACE(#body, '</td>', '</font></td>')
set #body = REPLACE(#body, '_x0020_', space(1))
set #body = Replace(#body, '_x003D_', '=')
set #body = Replace(#body, '<tr><TRRow>0</TRRow>', '<tr bgcolor=#F8F8FD>')
set #body = Replace(#body, '<tr><TRRow>1</TRRow>', '<tr bgcolor=#EEEEF4>')
set #body = Replace(#body, '<TRRow>0</TRRow>', '')
select #body --still empty
select #tableHTML = #tableHTML + #body
+ '</table></div></body></html>'
select #tablehtml --now empty!
select #tableHTML = '<div style="color:Black; font-size:11pt; font-family:tahoma; width:100px;">' + #tableHTML + '</div>'
select #tableHTML --still empty
EXEC msdb.dbo.sp_send_dbmail
#profile_name = #databaseMailProfileName,
#body = #tableHTML,
#body_format ='HTML',
#recipients = 'me#me.com',
#subject = 'Subject' ;
If I simply pass select * from #tableupdate or similar to the email, it sends me the data in a not very nice format.
The issue is the query below, returns NULL.
select #body =
(
select ROW_NUMBER() over(order by id) % 2 as TRRow,
td = col1,
td = col2,
td = col3,
td = col4,
td = col5
from #tableUpdate
where notificationType = 'NEWDATE'
order by clname
for XML raw('tr'), elements
)
Focus on this single query, and you will solve your issue. Without sample data of #tableUpdate, we can't solve your problem. However, since #body is NULL, concatenating anything to it will also yield NULL.
For example, select 1 + null, 'this string' + null will return two NULLs.
Thus, all of these set operators will still yield NULL for #body
set #body = REPLACE(#body, '<td>', '<td align=center><font face="tahoma">')
set #body = REPLACE(#body, '</td>', '</font></td>')
set #body = REPLACE(#body, '_x0020_', space(1))
set #body = Replace(#body, '_x003D_', '=')
set #body = Replace(#body, '<tr><TRRow>0</TRRow>', '<tr bgcolor=#F8F8FD>')
set #body = Replace(#body, '<tr><TRRow>1</TRRow>', '<tr bgcolor=#EEEEF4>')
set #body = Replace(#body, '<TRRow>0</TRRow>', '')
select #body --still empty
Then, you set #tableHTML to NULL by concatenating it with #body because #body IS NULL
select #tableHTML = #tableHTML + #body
+ '</table></div></body></html>'
Which leaves #tableHTML and #body with the value of NULL.
A stab at fixing this, since you are building a table, would be to set #body like so:
select #body =
cast((select ROW_NUMBER() over(order by id) % 2 as 'td',
'',
isnull(col1,'') as 'td',
'',
isnull(col2,'') as 'td',
'',
isnull(col3,'') as 'td',
'',
isnull(col4,'') as 'td',
'',
isnull(col5,'') as 'td'
from #tableUpdate
where notificationType = 'NEWDATE'
order by clname
for XML path('tr'), elements) as nvarchar(max))
I am using SQL+HTML script to send an email containing top 5 columns of a table mytable. Currently, I have all the column titles aligned centrally and each column entries aligned to the right using [th] and [td] repsectively. How can I make entries in Vendor column left aligned while keeping everything else the same?
DECLARE #dt datetime, #prev_dt datetime
SELECT #dt = dbo.GetDateOnly(getdate())
SELECT #prev_dt = dbo.GetDateOnly(getdate()-1)
SELECT top 5
Vendor,
OUTL_New_$,
OUTL_Old_$,
Outl_Diff_$ ,
OUTL_Diff_Perc,
Analyst
into #vpositive
FROM mytable
ORDER BY 4 DESC
--select * from #vpositive
if(##ROWCOUNT>0)
begin
--drop table #email
DECLARE #Body2 varchar(max)
declare #TableHead2 varchar(max)
declare #TableTail varchar(max)
Set #TableTail = '</table></body></html>';
Set #TableHead2 = '<html><head>' +
'<hr style="height:1px;border:none;color:#333;background-color:#333;">'+
'<H5 style="color: #000000; font-family:Arial">2: VENDOR LEVEL TOP 5 OUTL $ <font color="blue">INCREMENTS -</font></H5>' +
'<style>' +
'td {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:10pt;color:Black;text-align:right;font-family:Arial;} ' +
'th {border: solid black 1px;padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px;font-size:10pt;color:Black;text-align:center;font-family:Arial;} ' +
'</style>' +
'</head>' +
'<body><table cellpadding=0 cellspacing=0 border=0 width=auto>' +
'<tr bgcolor=#007336>'+
'<th><b><font color="white">Vendor</font></b></th>' +
'<th><b><font color="white">OUTL$ New</font></b></th>' +
'<th><b><font color="white">OUTL$ Old</font></b></th>' +
'<th><b><font color="white">OUTL$ Diff</font></b></th>' +
'<th><b><font color="white">OUTL$ Diff Perc</font></b></th>' +
'<th><b><font color="white">Analyst</font></b></th></tr>';
--Select information for the Report--
Select #Body2= (select
substring(Vendor,1,60) As [TD]
,'$ '+substring(parsename(convert(varchar,convert(money,cast(OUTL_New_$ as int)),1),2),1,13) As [TD]
,'$ '+substring(parsename(convert(varchar,convert(money,cast(OUTL_Old_$ as int)),1),2),1,13) As [TD]
,'$ '+substring(parsename(convert(varchar,convert(money,cast(OUTL_Diff_$ as int)),1),2),1,13) As [TD]
,substring(CAST(OUTL_Diff_Perc AS varchar(10)),1,4)+' %' As [TD]
,substring(Analyst,1,20) As [TD]
from #vpositive
For XML raw('tr'), Elements)
Set #Body = #TableHead2 + #Body2 + #TableTail
--Email
EXEC msdb.dbo.sp_send_dbmail
#recipients='abc#abc.com',
#subject = My analysis',
#body = #Body,
#body_format = 'HTML';
end
Did you try this:
<th align="left">
or this:
text-align: left;
On of the previous developers had a process that sent email alerts in the form of an html table in an email, this was done by triggering an stored procedure and passing the relevant parameters. This is a little outside my skills at the moment but im trying to get the same procedure to send an email for lateness. It works fine bar the formatting and layout. the query is -
SET #xml = CAST(( SELECT td = '<td align = "Center">' + CONVERT(VARCHAR(12),EmployeeName) + '</td>'
, td = '<td align = "Center">' + CONVERT(VARCHAR(12),StartTime) + '</td>'
, td = '<td align = "Center">' + CONVERT(VARCHAR(12),Late) + '</td>'
FROM #tempLateEmail
FOR XML PATH('tr'),TYPE).value('.','NVARCHAR(MAX)'
) AS NVARCHAR(MAX))
The body output is :
SET #body =
N'<style type="text/css">'
+ 'body {font-family: Arial;font-size:12px;} '
+ 'table{font-size:11px; border-collapse:collapse;table-layout: fixed} '
+ 'td{ border:1px solid black; padding:3px;} '
+ 'th{background-color:#F1F1F1;border:1px solid black; padding:3px;}'
+ 'h1{font-weight:bold; font-size:12pt}'
+ 'h2{font-weight:bold; font-size:10pt}'
+ '</style>'
+ '<body style="width:620px; margin:15px;">'
+ '<div style="margin:0 auto; width:300px">'
+ '<h1>Lateness Email on' + ' ' + convert(varchar, getdate(), 103) + '</h1>'
+ '</div>'
+ '<div style="float:left; width:250px">'
+ '<p>The following people appear to have been late today</p> '
+ '</div>'
+ '<div style="float:left; margin-left:20px; width:250px">'
+ '<div style="height:150px; overflow:auto">'
+ '<table width="250px">'
+ '<tr>'
+ '<th width = 100>Employee</th>'
+ '<th width =100>Expected Start Date</th>'
+ '<th width =100>Minutes Late</th>'
+ '</tr>'
+ #xml
+ '</table>'
+ '</div>'
+ '</div>'
+ '<div style="clear:both;"></div>'
+ '</body>'
SET #subject = 'Lateness Email for - ' + convert(varchar, getdate(), 103)
It then outputs them side by side instead of in a table. I understand why its doing it but I can not work out what to do about it. Hope i've provided enough info
as per Rohit Tiwari's comment there was indeed a <tr> missing from the end of the top secion of code -
SET #xml = CAST(( SELECT td = '<td align = "Center">' + CONVERT(VARCHAR(12),EmployeeName) + '</td>'
, td = '<td align = "Center">' + CONVERT(VARCHAR(12),StartTime) + '</td>'
, td = '<td align = "Center">' + CONVERT(VARCHAR(12),Late) + '</td>**<tr>** '
FROM #tempLateEmail
FOR XML PATH('tr'),TYPE).value('.','NVARCHAR(MAX)'
) AS NVARCHAR(MAX))
highlighted the update above.
I am trying to send a simple HTML email thru SQL stored procedure.
Is it possible adding a image such as company logo for the email result?
This is a part of stored procedure.
/*Create HTML*/
SET #TableHTML =
N'<H4>Production Alert (' + CONVERT(VARCHAR(10),GETDATE(),101) + ')</H4>' +
N'<table border="1">' +
N'<tr>' +
N' <td>Company</td>' +
N' <td width="70" align="CENTER">Department</td>' +
N' <td width="70" align="CENTER">Target</td>' +
N' <td width="70" align="CENTER">Shipped</td>' +
N' <td width="70" align="CENTER">Achievement by Yesterday</td>' +
N' <td width="70" align="CENTER">Achievement for this month</td>' +
N' <td width="70" align="CENTER">Difference</td>' +
N' <td width="70" align="CENTER">Catch Up QTY</td>' +
N'</tr>' +
CAST ( ( SELECT td = a.CompanyName, '', 'Right' AS "td/#align",
td = DepartmentName, '', 'Left' AS "td/#align",
td = ForecastQtyAcc, '', 'Right' AS "td/#align",
td = ShippedQtyAcc, '', 'Right' AS "td/#align",
td = ThePercentage, '', 'Right' AS "td/#align",
td = ThePercentageAll, '', 'Right' AS "td/#align",
td = TheDiff, '', 'Right' AS "td/#align",
td = CatchUpQTY, ''
FROM #Monthdata a
FOR XML PATH('tr'), TYPE
) AS NVARCHAR(MAX) ) +
N'</table>' ;
DROP TABLE #Monthdata
/Email it/
SET #TableHTML = #TableHTML +
N'' +
N''
See: Embed Images in emails created using SQL Server Database Mail