A pressão faz diamantes. Já falei isso por aqui, não?
Tenho recentemente trabalhado com alguns projetos mobile utilizando frameworks híbridos, como Ionic, Sencha e outros que surgem aos montes. A possibilidade de publicar tanto via browser como empacotar num cordova/phonegap dá a seu projeto uma expansibilidade generosa, podendo alcançar praticamente qualquer sistema operacional para usuários finais.
E assim vai. O fato é que, com isso em mente, pensei em fornecer uma solução nesse molde, só que para desktop. Se você é desenvolvedor web, sabe que não é suficiente abrir o arquivo html local no navegador para a execução de alguns scripts. Eles precisam ser “servidos” via HTTP. Ou seja, juntamente com o pacotão de htmls, css, js e tudo mais que seu app web tem, você precisa também de um servidor web. Para não mandar um apache para a máquina do seu usuário, ou mesmo ativar ou IIS, encontrei num canto da internet, mais especificamente o site CodePlex (se você não conhece, era esse cara quem mandava nos repositórios .NET antes do github entrar no ar) uma versão minimalista de um servidor http.
O código é bem “manual”, servindo as características de um servidor HTTP simples, respondendo a praticamente quaisquer tipos de arquivos. Os tipos servidos são definidos no web.config. Ele vêm com alguns exemplos configurados. Para atender à minha necessidade, obtive esta pequena lista:
E adicionei. Por fim, minha solução estava rodando dentro de um aplicativo desktop, o mesmo um console, com um servidor HTTP embutido.
Para aprendizado, vale muito. O código manipula requisições na base do socket, tanto que a instância o servidor usa a classe TcpListener, ao invés do HttpListener, como outros exemplos utilizam, conforme listarei no fim do artigo:
_myListener = new TcpListener(IPAddress.Any, Port);
O código original oferece configuração de diretório raiz e documento padrão, além da porta de escuta, tudo via web.config.
O código, com algumas alterações, pode ser visto aqui:
Não foi só isso que encontrei. Algumas alternativas foram igualmente interessantes, mas exigiam que você manipulasse cada request manualmente. São ótimos quando você quer especializar o processamento da resposta. São eles:
Coisa rápida. A necessidade veio do fórum, onde o colega rilton, especificamente na discussão do post Excel – Ativando Macros Automaticamente, onde um executável produzido pelo tutorial é gerado se uma identidade visual, ficando algo como:
Mas é claro que se quisermos transformar isso num produto, o ideal e que esse ícone fosse algo mais apresentável. Isso é possível facilmente através de ferramentas como o Visual Studio, como programadores .NET já o sabem. A boa notícia é que isso também é possível na linha de comando!
Isso é feito através do parâmetro do compilador csc (C# [Sharp] Compiler) chamado win32icon. Nele você deve mencionar o caminho de um arquivo de imagem com a extensão .ico (você pode baixar um exemplo aqui).
Para facilitar, coloque o arquivo .ico dentro da pasta do .csc a ser compilado e no Promp de Comand (veja como fazer isso aqui) use a seguinte sintaxe:
csc /win32icon:excel.ico AbreExcelComMacros.cs
O resultado é algo assim:
Note que o executável agora possui o mesmo ícone que o arquivo .ico.
Eis um assunto polêmico. Tão polêmico que desde a primeira versão vez em que tive contato com o Microsoft Excel e VBA, ouço falar dele. Para quem programa em VBA, ter as macros ativadas é um requisito para que todo seu código, fruto de suas longas horas de trabalho façam algum sentido na vida de seus usuários e clientes.
Infelizmente, não há como forçar sua ativação pelo próprio Excel. É preciso intervenção externa, seja via configuração (nível de segurança de macros) ou por aplicação externa. Existe a opção de certificados digitais, que é mais segura, mas exigem um nível de conhecimento e acesso ao computador muito específico. Não vou entrar em detalhes, pois acredito que se chegou até aqui, já deve ter passado por tudo isso.
A opção que vamos explorar para obter essa façanha é a “aplicação externa”, onde vamos produzir um aplicativo em um linguagem de programação que não o VBA para ativar as automaticamente as macros. A escolha desta opção se dá, principalmente pelo fato de facilitar a distribuição, uma vez que não é preciso ter acesso a máquina do usuário ou qualquer outra configuração. É a abordagem perfeita para aqueles que distribuem suas planilhas para clientes a distância.
O aplicativo externo
Utilizarei a linguagem C# rodando sobre .NET. Se não a conhece, recomendo dar uma lida neste curso, até porque, todas as instruções para seguir os passos do aplicativo que vamos construir estão nele.
O motivo da escolha é porque, primeiro, já trabalho com ela há mais de 10 anos (UAU!). Segundo, ela tem sido a linguagem mais utilizada para produzir aplicações para Windows na última década e vem sendo atualizada constantemente. Terceiro, se está lendo este artigo de um computador com Windows, você provavelmente já a tem instalada, tanto para executar como para criar aplicativo.
Nosso aplicativo será responsável por executar o Microsoft Excel, abrir o arquivo que contém as nossas macros com elas ativadas, sem intervenção do usuário. Bom demais para ser verdade não? Pois é isso mesmo que iremos fazer.
Criando o aplicativo
Passarei as instruções para que você possa criar o aplicativo sem precisar de programas adicionais. No futuro, você poderá facilitar o processo utilizando ferramentas mais avançadas, como o Visual Studio Express (que possui versões gratuitas). Para o momento, usaremos o Bloco de Notas e o compilador que vem com o .NET Framework, já instalado no seu Windows.
Vamos começar. Primeiro, crie uma pasta no seu disco no caminho:
C:\ExcelMacros.
É aqui que vamos trabalhar neste tutorial. Esse caminho não é obrigatório. No produto final, ele poderá estar onde quiser.
Obtenha seu arquivo Excel com suas macros. De preferência, coloque uma macro no Auto_Open ou no Workbook_Open para ter a visão imediata de que as macros estão sendo executadas. Salve o arquivo dentro da pasta que acabamos de criar acima. Para exemplo, vou usar um arquivo chamado ExcelComMacros.xlsm com o seguinte código VBA:
Private Sub Workbook_Open()
MsgBox "Funcionou!"
End Sub
Dessa forma, terei certeza se o código funcionou assim que executar o aplicativo.
Agora, abra o Bloco de Notas e insira nele o seguinte código:
usingSystem;usingSystem.Collections.Generic;usingSystem.Reflection;usingSystem.Threading;usingSystem.Windows.Forms;staticclass Program
{// variáveis de instãnciastaticobject oExcel =null;staticobject oBooks =null;staticobject oBook =null;staticobject oMissing =System.Reflection.Missing.Value;staticSystem.Globalization.CultureInfo ci = Thread.CurrentThread.CurrentCulture;[STAThread]staticvoid Main(){string CaminhoDoArquivo =@"C:\ExcelMacros\ExcelComMacros.xlsm";if(ExcelEstaInstalado()){try{if(System.IO.File.Exists(CaminhoDoArquivo)){
AbrirArquivo(CaminhoDoArquivo);}else{
MessageBox.Show(string.Format("O arquivo {0} não foi encontrado", CaminhoDoArquivo));}}catch(System.IO.IOException){
MessageBox.Show("Erro de acesso ao arquivo. Verifique o arquivo de configuração ou as permissões de pasta");}}else{
MessageBox.Show("Não foi possível encontrar a instalação do Microsoft Excel no seu computador");}
Application.Exit();}privatestaticvoid AbrirArquivo(string caminhoDoArquivo){object oFileName = caminhoDoArquivo;
oExcel = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
oExcel.GetType().InvokeMember("AutomationSecurity", BindingFlags.SetProperty, null, oExcel, newobject[]{1}, ci);
oExcel.GetType().InvokeMember("Visible", BindingFlags.SetProperty, null, oExcel, newobject[]{true}, ci);
oBooks = oExcel.GetType().InvokeMember("Workbooks", BindingFlags.GetProperty, null, oExcel, null, ci);
oBook = oBooks.GetType().InvokeMember("Open", BindingFlags.InvokeMethod, null, oBooks, newobject[]{ oFileName, oMissing, false}, ci);}publicstaticbool ExcelEstaInstalado(){
Type officeType = Type.GetTypeFromProgID("Excel.Application");if(officeType ==null){returnfalse;}else{returntrue;}}}
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
static class Program
{
// variáveis de instãncia
static object oExcel = null;
static object oBooks = null;
static object oBook = null;
static object oMissing = System.Reflection.Missing.Value;
static System.Globalization.CultureInfo ci = Thread.CurrentThread.CurrentCulture;
[STAThread]
static void Main()
{
string CaminhoDoArquivo = @"C:\ExcelMacros\ExcelComMacros.xlsm";
if (ExcelEstaInstalado())
{
try
{
if (System.IO.File.Exists(CaminhoDoArquivo))
{
AbrirArquivo(CaminhoDoArquivo);
}
else
{
MessageBox.Show(string.Format("O arquivo {0} não foi encontrado", CaminhoDoArquivo));
}
}
catch (System.IO.IOException)
{
MessageBox.Show("Erro de acesso ao arquivo. Verifique o arquivo de configuração ou as permissões de pasta");
}
}
else
{
MessageBox.Show("Não foi possível encontrar a instalação do Microsoft Excel no seu computador");
}
Application.Exit();
}
private static void AbrirArquivo(string caminhoDoArquivo)
{
object oFileName = caminhoDoArquivo;
oExcel = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
oExcel.GetType().InvokeMember("AutomationSecurity", BindingFlags.SetProperty, null, oExcel, new object[] { 1 }, ci);
oExcel.GetType().InvokeMember("Visible", BindingFlags.SetProperty, null, oExcel, new object[] { true }, ci);
oBooks = oExcel.GetType().InvokeMember("Workbooks", BindingFlags.GetProperty, null, oExcel, null, ci);
oBook = oBooks.GetType().InvokeMember("Open", BindingFlags.InvokeMethod, null, oBooks, new object[] { oFileName, oMissing, false }, ci);
}
public static bool ExcelEstaInstalado()
{
Type officeType = Type.GetTypeFromProgID("Excel.Application");
if (officeType == null)
{
return false;
}
else
{
return true;
}
}
}
Salve o arquivo com o seguinte nome e caminho:
C:\ExcelMacros\AbreExcelComMacros.cs
A extensão “.cs” é própria para arquivos da linguagem C#. Como o C# é uma linguagem compilada e não script (ver mais no curso já citado), precisamos compilar nosso pequeno programa para que ele se torne um executável. Para isso, no seu computador, navegue até a pasta:
C:\Windows\Microsoft.NET\Framework
Caso seu Windows seja 64bit, a pasta alvo será “Framework64”. Dentro desta pasta, você verá todas as versões do .NET Framework, necessários para executar programas em C# instalados no seu computador. Em nosso caso, vamos utilizar a versão v2.0.50727, ou simplesmente versão 2.0, que tem tudo o que precisamos e também porque temos mais certeza de que os computadores dos clientes o terão instalado.
Agora, abra o Prompt de Comando do Windows (sim, aquela tela preta esquisita) executando-a em modo administrador. Nele, navegue até a pasta que encontramos logo acima com o comando:
cd C:\Windows\Microsoft.NET\Framework\v2.0.50727
Nessa pasta, existe o executável chamado csc.exe (C–Sharp Compiler), que é nosso compilador, ou seja, o cara que vai transformar nosso “.cs” em um “.exe” pra lá de útil. Se algum dia chegou a estudar Java, ele é equivalente ao “javac”.
Por fim, vamos compilar nosso programa. Execute a seguinte linha de comando:
O que isso faz? Gera um arquivo “.exe” do nosso código C# pronto para ser executado. Se alguma coisa der errado aqui, como alguma mensagem de erro do compilador, volte e recomece desde a criação da pasta.
Os três parâmetros passados para o compilador foram:
out: o caminho do arquivo de saída
target: o tipo de aplicativo gerado, no caso, um Windows Application
no fim de tudo, o arquivo com o código fonte da aplicação
O resultado será provavelmente este:
Em destaque, nosso arquivo .exe gerado. Agora, execute-o (duplo-clique, enter, etc). Se tudo der certo, você verá seu arquivo Excel ser aberto com as macros ativadas.
Como funciona?
Aqui, há algumas coisas para explicar. Como a intenção aqui é ser simples, vou resumir ao máximo:
O código que faz a maior parte da mágica está dentro do método AbrirArquivo, que recebe o caminho do arquivo no Excel no disco. O código cria uma instância o aplicativo Excel, o que é bastante trivial até mesmo no VBA. A grande sacada está na propriedade AutomationSecurity, que aqui é definida para o nível de segurança mínimo, o que faz que com o Excel, neste contexto, aceite executar as macros automaticamente.
O resto é simples, abre o arquivo, define o aplicativo como visível, etc. Há algumas verificações “bônus”, como checar se o arquivo existe ou se o Excel está instalado no método ExcelEstaInstalado.
Outro detalhe que merece ser mencionado é o fato do código usar Reflection (no linguajar do VB, Late Binding) ao invés de fazer referência a bibliotecas. O motivo é que o Excel e todo o Office tem APIs versionadas. Se você fizer um código fazendo referência para a versão 2010, abrir na 2007 daria conflito. O código como está, evita esse problema.
Tudo pronto
De posse desta façanha, você pode agora distribuir suas planilhas com este arquivo de apoio que servirá para facilitar a execução de seus aplicativos. Para este caso em específico, se você dominar a linguagem C#, poderá incrementar seu aplicativo com uma séria e outras verificações.
Por essas e outras é muito bacana ser um programador! 😀
Mas primeiro, um pouco de história. Precisando renomear um série de arquivos em uma pasta do computador, vamos lá buscar na internet quais são as opções que existem para fazê-lo. Nada além do que o Windows é capaz. O mesmo permite que você renomeie em massa, selecionando vários arquivos, eles terão o mesmo nome com extenções diferentes, ou indexados se tiverem a mesma. No caso, o que queria era remover uma determinada string de vários arquivos, ou substituir por outra.
O resultado? Um programa em C# feito em modo Console que foi capaz de executar a proeza. Levou um tempo para refiná-lo, mas ficou bacana:
usingSystem;usingSystem.IO;publicclass RenomeiaArquivos
{publicstaticvoid Main(string[] args){// coleta os parâmetros, se houverif(args.Length<=0){// encerra
Console.WriteLine("Sem parâmetros?!?!?");return;}// 0 é a pastastring folder = args[0];// validaif(!Directory.Exists(folder)){
Console.WriteLine("Diretório inexistente");return;}// 1 é a string de procurastring find = args[1];// validaif(string.IsNullOrEmpty(find)){
Console.WriteLine("A string de procura não pode ser vazia");return;}// 2 é a string de substituiçãostring replace = args[2];foreach(string file in Directory.GetFiles(folder)){
Console.WriteLine(string.Format("Renomeando arquivo {0}", newobject[]{ file }));try{
File.Move(file, file.Replace(find, replace));
Console.WriteLine("OK");}catch{
Console.WriteLine("Ops! Não foi possível renomear este arquivo!");}}}}
using System;
using System.IO;
public class RenomeiaArquivos
{
public static void Main(string[] args)
{
// coleta os parâmetros, se houver
if (args.Length <= 0) {
// encerra
Console.WriteLine("Sem parâmetros?!?!?");
return;
}
// 0 é a pasta
string folder = args[0];
// valida
if (!Directory.Exists(folder)) {
Console.WriteLine("Diretório inexistente");
return;
}
// 1 é a string de procura
string find = args[1];
// valida
if (string.IsNullOrEmpty(find)) {
Console.WriteLine("A string de procura não pode ser vazia");
return;
}
// 2 é a string de substituição
string replace = args[2];
foreach(string file in Directory.GetFiles(folder)) {
Console.WriteLine(string.Format("Renomeando arquivo {0}", new object[] { file }));
try {
File.Move(file, file.Replace(find, replace));
Console.WriteLine("OK");
}
catch {
Console.WriteLine("Ops! Não foi possível renomear este arquivo!");
}
}
}
}
A chamada é simples, mas precisa ser feita em modo Console:
Abra o Prompt de comando
Aponte para a pasta em que está o executável (mais abaixo para download)