Estimado,
Buenas tardes.

En este post demostraré cómo exportar datos de una tabla de SQL Server a un archivo HTML o una variable de tipo VARCHAR, donde se presentarán dos Procedimientos muy similares, donde uno genera el HTML en forma de archivo físico en disco y el otro escribe el HTML generado en una variable de SALIDA.

También hice un post sobre esta misma funcionalidad, pero usando el CLR, que permite exportar una consulta a HTML de forma rápida y más práctica que usando OLE Automation. Si quieres saber más accede al post SQL Server – Cómo enviar el resultado de una consulta por correo electrónico en formato HTML usando el CLR (C#).

Requisitos previos

Si solo necesita utilizar el procedimiento en el que el HTML se devuelve como una variable de SALIDA, puede omitir los requisitos previos.

Para el procedimiento donde se genera un archivo físico en el disco necesito que tengas creado el procedimiento stpWrite_File_FSO, del cual hablé en la publicación Operaciones de archivos usando OLE Automation en SQL Server.

Vale la pena recordar que para utilizar OLE Automation, esta función debe estar habilitada en el servidor. Si no está habilitado, ver la publicación. Habilitación de la automatización OLE a través de T-SQL en SQL Server cómo hacer esto.

Creando una masa de datos para pruebas.

IF (OBJECT_ID('tempdb..##Teste') IS NOT NULL) DROP TABLE ##Teste
SELECT *
INTO ##Teste
FROM master.INFORMATION_SCHEMA.TABLES

Devolver HTML como variable de SALIDA

Esta funcionalidad debe usarse cuando necesites procesar o realizar alguna acción con el HTML generado, como enviar un correo electrónico con los datos de esta tabla, por ejemplo.

Ejemplo de uso:

DECLARE @HTML VARCHAR(MAX)

EXEC dbo.stpExporta_Tabela_HTML_Output
    @Ds_Tabela = '##Teste', -- varchar(max)
    @Ds_Saida = @HTML OUT -- varchar(max)

PRINT @HTML

Ejemplo de uso con texto centrado y ordenando los resultados por la columna TABLE_NAME:

DECLARE @HTML VARCHAR(MAX)

EXEC dbo.stpExporta_Tabela_HTML_Output
    @Ds_Tabela = '##Teste', -- varchar(max)
    @Ds_Saida = @HTML OUT, -- varchar(max)
    @Ds_Alinhamento = 'center',
    @Ds_OrderBy = 'TABLE_NAME'

PRINT @HTML

código fuente
Ver código fuente

CREATE PROCEDURE [dbo].[stpExporta_Tabela_HTML_Output]
    @Ds_Tabela [varchar](max),
    @Fl_Aplica_Estilo_Padrao BIT = 1,
	@Ds_Alinhamento VARCHAR(10) = 'left',
	@Ds_OrderBy VARCHAR(MAX) = '',
    @Ds_Saida VARCHAR(MAX) OUTPUT
AS
BEGIN
    
    
    SET NOCOUNT ON
    
    
    DECLARE
        @query NVARCHAR(MAX),
        @Database sysname,
        @Nome_Tabela sysname

    
    
    IF (LEFT(@Ds_Tabela, 1) = '#')
    BEGIN
        SET @Database = 'tempdb.'
        SET @Nome_Tabela = @Ds_Tabela
    END
    ELSE BEGIN
        SET @Database = LEFT(@Ds_Tabela, CHARINDEX('.', @Ds_Tabela))
        SET @Nome_Tabela = SUBSTRING(@Ds_Tabela, LEN(@Ds_Tabela) - CHARINDEX('.', REVERSE(@Ds_Tabela)) + 2, LEN(@Ds_Tabela))
    END

    
    SET @query = '
    SELECT ORDINAL_POSITION, COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, NUMERIC_SCALE
    FROM ' + @Database + 'INFORMATION_SCHEMA.COLUMNS 
    WHERE TABLE_NAME = ''' + @Nome_Tabela + '''
    ORDER BY ORDINAL_POSITION'
    
    
    IF (OBJECT_ID('tempdb..#Colunas') IS NOT NULL) DROP TABLE #Colunas
    CREATE TABLE #Colunas (
        ORDINAL_POSITION int, 
        COLUMN_NAME sysname, 
        DATA_TYPE nvarchar(128), 
        CHARACTER_MAXIMUM_LENGTH int,
        NUMERIC_PRECISION tinyint, 
        NUMERIC_SCALE int
    )

    INSERT INTO #Colunas
    EXEC(@query)

    
    
    IF (@Fl_Aplica_Estilo_Padrao = 1)
    BEGIN
    
    SET @Ds_Saida = '<html>
<head>
    <title>Titulo</title>
    <style type="text/css">
        table { padding:0; border-spacing: 0; border-collapse: collapse; }
        thead { background: #00B050; border: 1px solid #ddd; }
        th { padding: 10px; font-weight: bold; border: 1px solid #000; color: #fff; }
        tr { padding: 0; }
        td { padding: 5px; border: 1px solid #cacaca; margin:0; text-align:' + @Ds_Alinhamento + '; }
    </style>
</head>'
    
    END
    
    
    
    SET @Ds_Saida = ISNULL(@Ds_Saida, '') + '
<table>
    <thead>
        <tr>'


    -- Cabeçalho da tabela
    DECLARE 
        @contadorColuna INT = 1, 
        @totalColunas INT = (SELECT COUNT(*) FROM #Colunas), 
        @nomeColuna sysname,
        @tipoColuna sysname
    

    WHILE(@contadorColuna <= @totalColunas)
    BEGIN

        SELECT @nomeColuna = COLUMN_NAME
        FROM #Colunas
        WHERE ORDINAL_POSITION = @contadorColuna


        SET @Ds_Saida = ISNULL(@Ds_Saida, '') + '
            <th>' + @nomeColuna + '</th>'


        SET @contadorColuna = @contadorColuna + 1

    END



    SET @Ds_Saida = ISNULL(@Ds_Saida, '') + '
        </tr>
    </thead>
    <tbody>'


    
    -- Conteúdo da tabela

    DECLARE @saida VARCHAR(MAX)

    SET @query = '
SELECT @saida = (
    SELECT '


    SET @contadorColuna = 1

    WHILE(@contadorColuna <= @totalColunas)
    BEGIN

        SELECT 
            @nomeColuna = COLUMN_NAME,
            @tipoColuna = DATA_TYPE
        FROM 
            #Colunas
        WHERE 
            ORDINAL_POSITION = @contadorColuna



        IF (@tipoColuna IN ('int', 'bigint', 'float', 'numeric', 'decimal', 'bit', 'tinyint', 'smallint', 'integer'))
        BEGIN
        
            SET @query = @query + '
    ISNULL(CAST([' + @nomeColuna + '] AS VARCHAR(MAX)), '''') AS [td]'
    
        END
        ELSE BEGIN
        
            SET @query = @query + '
    ISNULL([' + @nomeColuna + '], '''') AS [td]'
    
        END
    
        
        IF (@contadorColuna < @totalColunas)
            SET @query = @query + ','

        
        SET @contadorColuna = @contadorColuna + 1

    END



    SET @query = @query + '
FROM ' + @Ds_Tabela + (CASE WHEN ISNULL(@Ds_OrderBy, '') = '' THEN '' ELSE ' 
ORDER BY ' END) + @Ds_OrderBy + '
FOR XML RAW(''tr''), Elements
)'
    
    
    EXEC tempdb.sys.sp_executesql
        @query,
        N'@saida NVARCHAR(MAX) OUTPUT',
        @saida OUTPUT


    -- Identação
    SET @saida = REPLACE(@saida, '<tr>', '
        <tr>')

    SET @saida = REPLACE(@saida, '<td>', '
            <td>')

    SET @saida = REPLACE(@saida, '</tr>', '
        </tr>')


    SET @Ds_Saida = ISNULL(@Ds_Saida, '') + @saida


    
    SET @Ds_Saida = ISNULL(@Ds_Saida, '') + '
    </tbody>
</table>'
    
            
END

Resultado final:

SQL Server x HTML2
Servidor SQL x HTML2

Exportar HTML a un archivo

Esta funcionalidad debe usarse cuando necesite generar un archivo físico en el disco o en la red que contenga el contenido de una tabla en formato HTML.

Ejemplo de uso:

EXEC dbo.stpExporta_Tabela_HTML 
    @Ds_Tabela = '##Teste', -- varchar(max)
    @Ds_Arquivo_Saida = 'C:\Teste.html' -- varchar(max)

código fuente
Ver código fuente

CREATE PROCEDURE [dbo].[stpExporta_Tabela_HTML]
    @Ds_Tabela [varchar](max),
    @Fl_Aplica_Estilo_Padrao BIT = 1,
    @Ds_Arquivo_Saida VARCHAR(500)
WITH EXECUTE AS CALLER
AS
BEGIN
    
    
    SET NOCOUNT ON
    
    
    DECLARE
        @query NVARCHAR(MAX),
        @Database sysname,
        @Nome_Tabela sysname,
        @Ds_Saida VARCHAR(MAX)

    
    
    IF (LEFT(@Ds_Tabela, 1) = '#')
    BEGIN
        SET @Database = 'tempdb.'
        SET @Nome_Tabela = @Ds_Tabela
    END
    ELSE BEGIN
        SET @Database = LEFT(@Ds_Tabela, CHARINDEX('.', @Ds_Tabela))
        SET @Nome_Tabela = SUBSTRING(@Ds_Tabela, LEN(@Ds_Tabela) - CHARINDEX('.', REVERSE(@Ds_Tabela)) + 2, LEN(@Ds_Tabela))
    END

    
    SET @query = '
    SELECT ORDINAL_POSITION, COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, NUMERIC_SCALE
    FROM ' + @Database + 'INFORMATION_SCHEMA.COLUMNS 
    WHERE TABLE_NAME = ''' + @Nome_Tabela + '''
    ORDER BY ORDINAL_POSITION'
    
    
    IF (OBJECT_ID('tempdb..#Colunas') IS NOT NULL) DROP TABLE #Colunas
    CREATE TABLE #Colunas (
        ORDINAL_POSITION int, 
        COLUMN_NAME sysname, 
        DATA_TYPE nvarchar(128), 
        CHARACTER_MAXIMUM_LENGTH int,
        NUMERIC_PRECISION tinyint, 
        NUMERIC_SCALE int
    )

    INSERT INTO #Colunas
    EXEC(@query)

    
    
    IF (@Fl_Aplica_Estilo_Padrao = 1)
    BEGIN
    
    SET @Ds_Saida = '<html>
<head>
    <title>Titulo</title>
    <style type="text/css">
        table { padding:0; border-spacing: 0; border-collapse: collapse; }
        thead { background: #00B050; border: 1px solid #ddd; }
        th { padding: 10px; font-weight: bold; border: 1px solid #000; color: #fff; }
        tr { padding: 0; }
        td { padding: 5px; border: 1px solid #cacaca; margin:0; }
    </style>
</head>'
    
    END
    
    
    
    SET @Ds_Saida = ISNULL(@Ds_Saida, '') + '
<table>
    <thead>
        <tr>'


    -- Cabeçalho da tabela
    DECLARE 
        @contadorColuna INT = 1, 
        @totalColunas INT = (SELECT COUNT(*) FROM #Colunas), 
        @nomeColuna sysname,
        @tipoColuna sysname
    

    WHILE(@contadorColuna <= @totalColunas)
    BEGIN

        SELECT @nomeColuna = COLUMN_NAME
        FROM #Colunas
        WHERE ORDINAL_POSITION = @contadorColuna


        SET @Ds_Saida = ISNULL(@Ds_Saida, '') + '
            <th>' + @nomeColuna + '</th>'


        SET @contadorColuna = @contadorColuna + 1

    END



    SET @Ds_Saida = ISNULL(@Ds_Saida, '') + '
        </tr>
    </thead>
    <tbody>'


    
    -- Conteúdo da tabela

    DECLARE @saida VARCHAR(MAX)

    SET @query = '
SELECT @saida = (
    SELECT '


    SET @contadorColuna = 1

    WHILE(@contadorColuna <= @totalColunas)
    BEGIN

        SELECT 
            @nomeColuna = COLUMN_NAME,
            @tipoColuna = DATA_TYPE
        FROM 
            #Colunas
        WHERE 
            ORDINAL_POSITION = @contadorColuna



        IF (@tipoColuna IN ('int', 'bigint', 'float', 'numeric', 'decimal', 'bit', 'tinyint', 'smallint', 'integer'))
        BEGIN
        
            SET @query = @query + '
    ISNULL(CAST(' + @nomeColuna + ' AS VARCHAR(MAX)), '''') AS [td]'
    
        END
        ELSE BEGIN
        
            SET @query = @query + '
    ISNULL(' + @nomeColuna + ', '''') AS [td]'
    
        END
    
        
        IF (@contadorColuna < @totalColunas)
            SET @query = @query + ','

        
        SET @contadorColuna = @contadorColuna + 1

    END



    SET @query = @query + '
FROM ' + @Ds_Tabela + '
FOR XML RAW(''tr''), Elements
)'
    
    
    EXEC tempdb.sys.sp_executesql
        @query,
        N'@saida NVARCHAR(MAX) OUTPUT',
        @saida OUTPUT


    -- Identação
    SET @saida = REPLACE(@saida, '<tr>', '
        <tr>')

    SET @saida = REPLACE(@saida, '<td>', '
            <td>')

    SET @saida = REPLACE(@saida, '</tr>', '
        </tr>')


    SET @Ds_Saida = ISNULL(@Ds_Saida, '') + @saida


    
    SET @Ds_Saida = ISNULL(@Ds_Saida, '') + '
    </tbody>
</table>'

    
    IF (@Ds_Saida IS NOT NULL)
    BEGIN
        
        EXEC dbo.stpEscreve_Arquivo_FSO
            @String = @Ds_Saida, -- varchar(max)
            @Ds_Arquivo = @Ds_Arquivo_Saida -- varchar(1501)
            
            
        PRINT 'Arquivo com o conteúdo da tabela "' + @Ds_Tabela + '" foi gerado no caminho "' + @Ds_Arquivo_Saida + '"'
            
            
    END
    ELSE
        PRINT 'O retorno dos dados está vazio.'
            
END

Resultado final:

SQL Server x HTML
Servidor SQL frente a HTML

Eso es todo, amigos.
¡Hasta la próxima!