Oi! Seja bem-vindo!

Hoje vou mostrar a você como exportar SELECT para HTML, usando uma técnica simples que tem sido bastante útil para mim e meus clientes em inúmeras ocasiões onde precisamos publicar dados do SQL na WEB.

Para que serve exportar SELECT para HTML?

Embora os aplicativos estejam cada vez mais populares, fornecer acesso as informações via browser (acesso WEB) ainda é mais amigável em muitas ocasiões, afinal, já temos aplicativos o suficiente em nossos celulares, certo?

Pois bem, para expormos dados na WEB, eles precisam estar em HTML.

Muitas vezes os sites possuem uma interface para copiarmos e colarmos informações (ex: meu site wordpress que você está visualizando possui), porém você á tentou copiar o resultado de uma consulta SQL e colar em algum site? 🙂

Se sim, você sabe do que estou falando: a não ser que o site tenha algum tipo de ferramenta para tratar tabelas, as informações ficam inteiramente bagunçadas.

Além disso, mesmo que o site possua alguma ferramenta para gerenciamento de tabelas, na maioria das vezes você não pode copiar e colar o resultado, e ai tome trabalho braçal… Agora, se você possuir o HTML pronto, então basta copiar e colar no site.

Como exportar SELECT para HTML

Gostaria de ter alguma técnica super automática para te mostrar, que exportasse o resultset do seu SELECT diretamente para HTML, mas infelizmente, até o momento, o jeito é codificar as TAGs HTML na mão mesmo.

Porém, com a procedure que criei (código abaixo), você conseguirá, na maioria das vezes, exportar os SELECTs para HTML de forma muito simples. Aqui vai o script completo usado no vídeo:



------------------------------------------------------------------
-- Query -> Tabela HTML
------------------------------------------------------------------
--------------------------------------------------
-- Banco de dados para nosso teste
--------------------------------------------------
-- Banco de testes
use master
if db_id('curso') is not null 
	drop database curso
go
create database curso
go
use curso
go
create table produtos (
	id smallint identity(1,1) primary key,
	nm varchar(100),
	vl decimal(10,2),
	ic_ativo bit not null default (1)
)
insert produtos (nm, vl) values 
	('Mouse Gammer 25 botões', 200),
	('Teclado Gammer 350 teclas', 300),
	('Monitor 32 Pol Full HD', 1000),
	('RAM DDR4 4GB Powerturbo', 500),
	('CPU Nasa 10Ghz', 2000),
	('HD SSD 1TB', 2000)

--------------------------------------------------
-- Procedure de geração da tabela HTML
--------------------------------------------------
if object_id('usp_resultset_html') is not null drop proc usp_resultset_html
go
create proc dbo.usp_resultset_html (@consulta nvarchar(max), @titulo_tabela nvarchar(300) = '', @css nvarchar(max) = 'default')
as begin 
	begin transaction
	set nocount on
	set xact_abort on
	declare @colunas varchar(max)
	declare @html_final nvarchar(max)
	declare @html_parcial nvarchar(max)
	declare @sql nvarchar(max)
	-- Obtem colunas do select original e converte para TDs
	set @colunas = stuff((select ', [' + name + '] as td' from sys.dm_exec_describe_first_result_set(@consulta, null, 0) for xml path('')), 1, 1, '')

	-- Define nome da tabela temporária com newid para permitir execução simultanea por diversos terminais
	declare @table_name varchar(50)
	set @table_name = 'tb' + convert(varchar, abs(checksum(newid())))

	-- Altera query original para salvar o resultado da query na tabela temporária
	-- Ex: DE: "select * from produtos" PARA: "select * into tb123456 from produtos"
	if charindex('from', @consulta) = 0
		begin
			-- selects sem "from tabela", exemplo: select 1, 2
			set @consulta = @consulta + ' into ' + @table_name
		end
	else
		begin
			-- Selects normais, com tabelas
			set @consulta = replace(@consulta, 'from', ' into ' + @table_name + ' from ')
		end
	execute (@consulta)

	-- Cria html a partir da tabela temporária salva
	set @html_final = '<table class="sql_tabela">'
	if @titulo_tabela <> '' set @html_final = @html_final + '<caption>' + @titulo_tabela + '</caption>'
	set @html_final = @html_final + '<thead><tr>'
	set @sql = 'set @html_parcial= (select column_name as th from information_schema.columns where table_name = ''' + @table_name + ''' for xml path(''''))'
	execute sp_executesql @sql, N'@html_parcial varchar(max) out', @html_parcial out
	set @html_final = @html_final + @html_parcial
	set @html_final = @html_final + '</tr></thead>'
	set @html_final = @html_final + '<tbody>'
	set @sql = 'set @html_parcial= (select ' + @colunas + ' from ' + @table_name + ' for xml raw(''tr''), elements)'
	execute sp_executesql @sql, N'@html_parcial nvarchar(max) out', @html_parcial out
	set @html_final = @html_final + @html_parcial
	set @html_final = @html_final + '</tbody></table>'

	-- Adiciona CSS:
	if @css is null set @css = ''
	if @css = 'default'
		set @css = '
			<style>
				.sql_tabela {
					border-spacing: 0px;
				}
				.sql_tabela caption {
					padding: 5px;
					border: 1px solid #F0F0F0;
					text-align: center;
				}
				.sql_tabela thead {
					background: #FCFCFC;
				}
				.sql_tabela th {
					padding: 1px 10px 1px 5px;
					border: 1px solid #F0F0F0;
					font-weight: normal;    
					text-align: left;
					word-wrap: break-word;
					max-width: 200px;
				}
				.sql_tabela body {
				}
				.sql_tabela td {
					padding: 1px 10px 1px 5px;
					border: 1px solid #F0F0F0;
					word-wrap: break-word;
					max-width: 200px;
				}
			</style>'
	if @css = 'default_inline'
		begin
			set @css = ''
			set @html_final = replace(@html_final, '<table class="sql_tabela">', '<table style="border-spacing: 0px;">')
			set @html_final = replace(@html_final, '<caption>', '<caption style="padding: 5px; border: 1px solid #F0F0F0; text-align: center;">')
			set @html_final = replace(@html_final, '<thead>', '<thead style="background: #FCFCFC;">')
			set @html_final = replace(@html_final, '<th>', '<th style="padding: 1px 10px 1px 5px; border: 1px solid #F0F0F0; font-weight: normal; text-align: left; word-wrap: break-word; max-width: 200px;">')
			set @html_final = replace(@html_final, '<td>', '<td style="padding: 1px 10px 1px 5px; border: 1px solid #F0F0F0; word-wrap: break-word; max-width: 200px;">')
		end
	set @html_final = @css + @html_final
	
	-- Mostra HTML
	select @html_final

	-- Exclui tabela temporária
	execute ('drop table ' + @table_name)
	rollback transaction
end
go


--------------------------------------------------
-- Exemplos de uso
--------------------------------------------------
-- Execução direta
execute usp_resultset_html 'select * from produtos'

-- Execução exportando para arquivo (ative o comando abaixo em Query -> SQLCMD mode)
-- DICA: Para resultados grandes SEMPRE use esse comando
!!bcp "exec curso.dbo.usp_resultset_html 'select * from produtos', 'Tabela Produtos'" queryout "C:\tmp\tabela_produtos.html" -c -t, -T -S -C ACP


--------------------------------------------------
-- Excluir dados de teste
--------------------------------------------------
use master
go
drop database curso
go




 

Não funcionou para meu SELECT! O que eu faço?

Já aconteceu comigo também…. 🙂

As vezes, as querys são muito complexas, tem códigos dinâmicos ou outra coisa qualquer…. e isso faz minha singela procedure não atender o que você precisa…. 🙁  sorry por isso….

Mas nem tudo está perdido! Quando esse tipo de coisa ocorre comigo, ao invés de quebrar a cabeça ajustando a procedure, eu simplesmente salvo o resultado da consulta em uma tabela temporária, e depois mando para a procedure o bom e velho “SELECT * FROM TABELA_TEMPORARIA”.

Não mostrei isso no vídeo porque se já vimos em outros momentos e provavelmente você sabe exatamente como implementar essa solução…. certo? Se tiver alguma dúvida, me fala que a gente conversa.

CONCLUSÃO

Gostou? Particularmente, já usei essa estratégia em cenários, como:

1) Publicar relatórios de acompanhamento para meus clientes visualizarem via browser.

2) Criar exercícios e provas para meus alunos, que eles podem acessar pela web.

3) Publicar exemplos em sites de internet.

Em qualquer dessas ocasiões, a exportação de SELECT para HTML que te mostrei foi bem efetiva.

No entanto, a Microsoft bem que poderia implementar uma geração de HTML a partir do resultset, ou algo como um “for html” como existe no caso dos XMLs (for xml), né?

Com quase tudo na WEB hoje em dia, creio que uma hora dessas eles vão criar algo assim, até por isso não faço questão de evoluir essa minha procedure. Acredito que uma hora ou outra ela se tornará obsoleta, mas até lá, ela segue me ajudando… e muito!

Espero que tenha gostado do artigo, nos vemos no próximo!

Abraço do seu amigo Josué 🙂

 

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *