Convert a SQL query result table to an HTML table for email
Here is one way to do it from an article titled "Format query output into an HTML table - the easy way [archive]". You would need to substitute the details of your own query for the ones in this example, which gets a list of tables and a row count.
declare @body varchar(max)
set @body = cast( (
select td = dbtable + '</td><td>' + cast( entities as varchar(30) ) + '</td><td>' + cast( rows as varchar(30) )
from (
select dbtable = object_name( object_id ),
entities = count( distinct name ),
rows = count( * )
from sys.columns
group by object_name( object_id )
) as d
for xml path( 'tr' ), type ) as varchar(max) )
set @body = '<table cellpadding="2" cellspacing="2" border="1">'
+ '<tr><th>Database Table</th><th>Entity Count</th><th>Total Rows</th></tr>'
+ replace( replace( @body, '<', '<' ), '>', '>' )
+ '</table>'
print @body
Once you have @body
, you can then use whatever email mechanism you want.
how do I convert a select statement result into an HTML table in SQL Server?
Make use of FOR XML PATH (learned from others here). something like this:
SET @tableHTML =
N'<table>' +
N'<tr><th>SpecialOfferID</th>
<th>Description</th>
<th>Type</th>
<th>Category</th>
<th>StartDate</th>
<th>EndDate</th>
</tr>' +
CAST ( (
SELECT td = CAST([SpecialOfferID] AS VARCHAR(100)),'',
td = [Description],'',
td = [Type],'',
td = [Category] ,'',
td = CONVERT(VARCHAR(30),[StartDate],120) ,'',
td = CONVERT(VARCHAR(30),[EndDate],120)
FROM [AdventureWorks].[Sales].[SpecialOffer]
ORDER BY [SpecialOfferID]
FOR XML PATH('tr'), TYPE
) AS NVARCHAR(MAX) ) +
N'</table>'
Returning query to an HTML table alert email with TSQL dbmail
Because the requirement is to pass multiple rows to the body of the email, it would be best served in a tabular format.
This can be achieved by including in the email body, an HTML table of dossiers that meet the criteria.
Simply replace the column name's with the correct name's from table bo.
Let's break down the elements individually:
CREATE PROCEDURE dbo.DossierEmailSend
AS
Create a holding table for the dossiers that met the criteria
DECLARE @dossiers TABLE (col1 varchar(100), col2 varchar(100), col3 varchar(100), col4 varchar(100));
Insert the dossiers that met the criteria
INSERT INTO @dossiers
SELECT col1, col2, col3, convert(varchar,col4) col4
FROM bo
WHERE nmdos LIKE '%preço%'
AND datafinal = DATEADD(day, -1, CONVERT(date, GETDATE()))
Create a row check to determine whether to send the email or not
DECLARE @rows int;
SET @rows = (SELECT COUNT(*) FROM @dossiers)
Check if any dossiers met the criteria
IF @rows > 0
BEGIN
Set the body elements
DECLARE @message varchar(1000);
-- declare the xml data to pass to the HTML body
DECLARE @xml NVARCHAR(MAX);
-- body will hold the HTML formatted table in the email
DECLARE @body NVARCHAR(MAX);
Create the columns that will hold each row of data as xml
SET @xml = CAST(( SELECT col1 AS 'td','',col2 AS 'td','', col3 AS 'td','', col4 AS 'td'
FROM @dossiers
FOR XML PATH('tr'), ELEMENTS ) AS NVARCHAR(MAX))
Set the HTML for the body
SET @body ='<html><body><H3>Dossier Info</H3>
<table border = 1>
<tr>
<th> col1 </th> <th> col2 </th> <th> col3 </th> <th> col4 </th></tr>'
Stitch everything together, appending the HTML table
SET @body = @body + @xml +'</table></body></html>'
SET NOCOUNT ON
Send the email and append the data table to the body
EXEC dbo.uspSendEmail 'Dossiers FOund', 'Convert a SQL Query Result Table to an HTML Table for Email@aaaa', @body, NULL, 'CC EMAIL 1'
SET NOCOUNT OFF
END
The finished solution should look something like the below:
CREATE PROCEDURE dbo.DossierEmailSend
AS
--Create a holding table for the dossiers that met the criteria
DECLARE @dossiers TABLE (col1 varchar(100), col2 varchar(100), col3 varchar(100), col4 varchar(100));
--Insert the dossiers that met the criteria
INSERT INTO @dossiers
SELECT col1, col2, col3, convert(varchar,col4) col4
FROM bo
WHERE nmdos LIKE '%preço%'
AND datafinal = DATEADD(day, -1, CONVERT(date, GETDATE()))
--Create a row check to determine whether to send the email or not
DECLARE @rows int;
SET @rows = (SELECT COUNT(*) FROM @dossiers)
--Check if any dossiers met the criteria
IF @rows > 0
BEGIN
--Set the body elements
DECLARE @message varchar(1000);
-- declare the xml data to pass to the HTML body
DECLARE @xml NVARCHAR(MAX);
-- body will hold the HTML formatted table in the email
DECLARE @body NVARCHAR(MAX);
--Create the columns that will hold each row of data as xml
SET @xml = CAST(( SELECT col1 AS 'td','',col2 AS 'td','', col3 AS 'td','', col4 AS 'td'
FROM @dossiers
FOR XML PATH('tr'), ELEMENTS ) AS NVARCHAR(MAX))
--Set the HTML for the body
SET @body ='<html><body><H3>Dossier Info</H3>
<table border = 1>
<tr>
<th> col1 </th> <th> col2 </th> <th> col3 </th> <th> col4 </th></tr>'
--Stitch everything together, appending the HTML table
SET @body = @body + @xml +'</table></body></html>'
SET NOCOUNT ON
--Send the email and append the data table to the body
EXEC dbo.uspSendEmail 'Dossiers FOund', 'Convert a SQL Query Result Table to an HTML Table for Email@aaaa', @body, NULL, 'CC EMAIL 1'
SET NOCOUNT OFF
END
Convert SQL Server table into HTML using TSQL
There is a script created by Shnugo which can be found here with his comments, and methods to call it. I specifically use to build a HTML table when I need to send results with DBMAIL.
Here's how
/************************************************************************************************
Function to build a HTML table.
Created by Shnugo on SO: https://stackoverflow.com/a/39487565/6167855
Usage:
declare @body xml =
(select AdminTools.dbo.ufn_CreateHTMLTable (
(select * from SomeTable for xml path ('row'),elements xsinil)
,null,null,null))
--CSS to make borders, which makes us change datatype
declare @body_html varchar(max)
set @body_html =
'<style type="text/css" media="screen,print">
.center
{
text-align: center;
}
table,th
{
border: 1px solid black;
}
table,tr
{
border: 1px solid black;
}
table,td
{
border: 1px solid black;
}
</style>'
+ cast(@body as varchar(max))
Then @body_html for sp_send_dbmail
************************************************************************************************/
CREATE FUNCTION [dbo].[ufn_CreateHTMLTable]
(
@SelectForXmlPathRowElementsXsinil XML
,@tblClass VARCHAR(100) --NULL to omit this class
,@thClass VARCHAR(100) --same
,@tbClass VARCHAR(100) --same
)
RETURNS XML
AS
BEGIN
RETURN
(
SELECT @tblClass AS [@class]
,@thClass AS [thead/@class]
,@SelectForXmlPathRowElementsXsinil.query(
N'let $first:=/row[2]
return
<tr>
{
for $th in $first/*
return <th>{if(not(empty($th/@caption))) then xs:string($th/@caption) else local-name($th)}</th>
}
</tr>') AS thead
,@tbClass AS [tbody/@class]
,@SelectForXmlPathRowElementsXsinil.query(
N'for $tr in /row
return
<tr>{$tr/@class}
{
for $td in $tr/*
return
if(empty($td/@link))
then <td>{$td/@class}{string($td)}</td>
else <td>{$td/@class}<a href="{$td/@link}">{string($td)}</a></td>
}
</tr>') AS tbody
FOR XML PATH('table'),TYPE
)
END
GO
Getting bad format on float values when exporting query to html table
you are using cast to show the values in the html-table:
SET @cols = ''SET @html = CAST(( SELECT '' + @cols + '' FROM #dynSql ' + @orderBy + ' FOR XML PATH(''''tr''''), ELEMENTS XSINIL) AS nvarchar(max))''
MS-Help tells you more, but basically this is the automatic behavior of cast with a float value.
You should try to already convert your float-fields to the desired format in the query you pass, using the STR()
function, see str function description
Related Topics
Is Cross-Origin Postmessage Broken in Ie10
Flexbox Affects Overflow-Wrap Behavior
How to Get a Web Page Header/Footer Printed on Every Page
Remove Blur Effect on Child Element
How to Scale a Stubborn Svg Embedded with the <Object> Tag
Html5 Phone Number Validation with Pattern
Can <Span> Tags Have Any Type of Tags Inside Them
HTML Table Cell Width for Different Rows
Uppercase or Lowercase Doctype
Why Does Inline-Block Cause This Div to Have Height
How Does Selenium Click on Elements That Are 50% on Screen and 50% Not on Screen
Turn Off Chrome/Safari Spell Checking by HTML/Css
How to Get a Background Image to Print Using CSS
Why Is an Element with Position: Fixed Moving with a Non-Positioned Sibling
How to Add a Font Awesome Icon to Input Field
Which Is More Correct: <H1><A>...</A></H1> or <A><H1>...</H1></A>