Continuação - Delphi e OpenOffice(BROffice) - Parte 2
Trabalhando com Arquivos e Planilhas no Calc
I – REQUISITOS NECESSÁRIOS PARA O MÓDULO
Ter entendido e treinado a versão do artigo apresentada como introdução.
Delphi e OpenOffice(BROffice) - Parte 2
II – OBJETIVOS
Entender a dinâmica de trabalho com planilhas e arquivos do Calc. Os principais cuidados para ter sucesso no processo de transferência de dados OLE entre Delphi 7 e BrOffice.
III – IMPORTANTE
Atente para os comandos, já que a linguagem é case-sensitive.
IV – INICIANDO
Vamos criar uma nova aplicação, e nela adiconaremos os seguintes componentes do Delphi: Um Edit, um SpinEdit, um StringGrid, um CheckBox, um ListBox e como não pode faltar, um botão.
Deixo a formatação da tela para você. Muitas vezes os tutoriais induzem a ter que fazer tudo dentro de uma certa configuração, eu não pretendo fazer isso agora. O que faremos nessa parte de nosso tutorial? Simples!! Através do spinedit, definiremos o número de planilhas que serão criadas em nossa aplicação, não edite o campo índice do stringgrid, pois é ele quem coloca as planilhas em ordem dentro da pasta (o mesmo que no Excel), a medida que o spinedit tem seu valor modificado o número de linhas é incrementado ou decrementado e automaticamente gera os índices. No campo do Edit você poderá escolher qualquer nome para o arquivo e o destino do arquivo. Quando iniciamos o processamento, podemos marcar a opção que verifica se já existe uma planilha com um dos nomes que estamos registrando (não podem haver duas planilhas com o mesmo nome na mesma pasta); e para finalizar, vamos capturar o nome das planilhas que registramos e seus respectivos índices dentro da pasta.
Vamos inserir o código em nosso sistema e iniciar as explicações necessárias. Os eventos dos componentes estão com seus nomes sublinhados.
procedure TForm1.FormShow(Sender: TObject);
begin
StringGrid1.Cells[0,0] := 'Indice';
StringGrid1.Cells[1,0] := 'Nome da Planilha';
SpinEdit1.OnChange(sender);
end;
procedure TForm1.SpinEdit1Change(Sender: TObject);
var
x : Integer;
begin
If (SpinEdit1.Value = 1) then
begin
ShowMessage('Uma planilha deve estar presente obrigatoriamente na pasta');
SpinEdit1.Value := 1;
StringGrid1.RowCount := 2;
end else begin
StringGrid1.RowCount := SpinEdit1.Value + 1;
For x := 1 to StringGrid1.RowCount do
StringGrid1.Cells[0,x] := Format('%d',[x - 1]);
end;
end;
O evento onShow do formulário simplesmente coloca os indices nas linhas quando a aplicação é iniciada e atribui o número de linhas pelo evento onChange do SpinEdit1. Nada de “phenomenal”. O evento onChange do spinEdit1 tem um pequeno if limitando o número de planilhas existentes para um documento. Para que a pasta possa existir, ela necessita de pelo menos uma planilha.
Vamos para a parte nervosa!!!
procedure TForm1.Button1Click(Sender: TObject);
var
N, x : SHORT;
Remover : array[0..2] of String;
begin
BrOffice := CreateOleObject('com.sun.star.ServiceManager');
Desktop := BrOffice.CreateInstance('com.sun.star.frame.Desktop');
Documento := Desktop.LoadComponentFromURL('private:factory/scalc', '_blank', 0,
VarArrayCreate([0,-1], varVariant));
//Vai guardar o nome para excluir as planilhas originais na sequência
For x := 0 to 2 do
Remover[x] := Documento.Sheets.getByIndex(x).Name;
{ Insere as planilhas nomeadas pelo usuarios, baseados no índice de nosso
sistema }
For x := 1 to StringGrid1.RowCount - 1 do
begin
if CheckBox1.Checked then
begin
if not Documento.Sheets.hasByName(StringGrid1.Cells[1, x]) then
Documento.getSheets.insertNewByName(StringGrid1.Cells[1, x] , x - 1)
else
ShowMessageFmt('A planilha que você inseriu com o nome de %s não será criada' + #13 +
'porque ela já existe na pasta!',[StringGrid1.Cells[1, x]]);
end else
Documento.getSheets.insertNewByName(StringGrid1.Cells[1, x] , x - 1);
end;
{ remove as planilhas criadas automaticamente pelo sistema
veremos mais tarde como fazer a exclusão ou renomear através de um módulo
chamado de UNO }
For x := 0 to 2 do
Documento.getSheets.removeByName(Remover[x]);
{ Recupera novamente a quantidade de planilhas registrada ou inseridas e
apresenta o nome no ListBox }
N := Documento.getSheets.GetCount;
For x := 0 to Pred(N) do
lbNomes.Items.Insert(x, Format('Index da Plan: %d - Nome: %s',
[x, Documento.Sheets.getByIndex(x).Name]));
end;
Vamos agora enteder o que foi programado. O primeiro bloco como podemos assim dizer, somente foi feita a declaração das variáveis para criar os elementos do Broffice. No primeiro for lhe foi apresentado a seguinte situação:
Documento.Sheets.getByIndex(x).Name; A variável documento armazena as propriedades, funções e procedimentos relativos ao documento; avançamos para a propriedade da planilha (
Sheets) e através da função
getByIndex capituramos o índice da planilha dentro da pasta. Obviamente que a propriendade
Name nos retornará o nome da planilha. O que fiz não foi pegar o número de planilhas na pasta, isso seria o mais correto, porém, como sabemos que a pasta sempre conterá três planilhas (a não ser que o miserável do usuário altere alguma configuração) então não coletei esse valor. Mas esse procedimento seria o mais correto, capturar o número de planilhas de uma pasta e na sequência obter seus nomes.
No segundo
for, é iniciado o processo de inserir as planilhas que registramos no StringGrid. O que faz o CheckBox1? Ele questiona se o usuário deseja verificar se já existe o nome da planilha na pasta em que estamos trabalhando. Através da função
hasByName('NomeDaPlanilha') podemos verificar se ela já existe. É uma função simples e seu único parâmetro é o nome da planilha. É uma função Boleana, se o nome existe, o retorno da função é True, caso contrário, False – obviamente!
Como foi dito, através da função
hasByName verificamos se existe alguma planilha contendo o nome que passamos em nosso grid; se não existir, vamos usar uma função nova chamada
insertNewByName('NomeDaPlanilha', Índice). O primeiro parâmetro da função é uma String e o segundo um valor Inteiro. Veja também que, um documento sempre será um container para armazenar diversas folhas ou planilhas como sabemos. Assim
getSheets() retornará todos os objetos de planilhas dentro da pasta. O Índice da função
insertNewByName sempre inicia do
ZERO (0). O que estou querendo dizer é, se quiser inserir uma nova planilha com o nome de 'Contabilidade', em uma pasta e que ela esteja na segunda folha, diminua o valor real menos 1 – A primeira planilha tem o índice Zero, a segunda Um, a terceira Dois e assim por diante.
Para remover uma planilha você usará a função
removeByName('NomeDaPlanilha'), é bem simples e seu parâmetro é uma String. Coloque o nome da planilha que deseja excluir e pronto. Em nosso exemplo, isso foi feito colocando os nomes em um array quando pressionamos o botão
Executar Calc. Não haveria necessidade de fazer isso, já que sabemos que sempre os nomes serão 'Planilha1', 'Planilha2' e 'Planilha3'. Logo o exemplo do primeiro for foi meramente ilustrativo conforme explicado inicialmente.
Aumentando um pouco mais a complexidade!!!! Não é igual ao Excel....
O BrOffice é uma ferramenta desenvolvida por diversos profissionais e seu objetivo e atender os diversos sistemas operacionais que estão presentes no mercado. Vamos para o segundo botão do nosso pequeno programa e que executa o comando salvar da planilha. Um detalhe importante e por isso fiz essa pequena introdução, quando salvamos um documento no BrOffice, devemos passar o caminho contendo um formato diferente, parecido com as plataformas Linux, você sempre passará o caminho para salvar o arquivo no seguinte formato:
'file:///' + Pastas + NomeDoDocumento + extensão. Outro pequeno detalhe, as barras devem ser as barras de data e não as barras invertidas que são o padrão Microsoft. Se você pensar em salvar um arquivo em algo parecido com:
C:\Meus Documentos\Minha Pasta\Subpasta\MinhaPlanilha.odt, deverá converter isso para:
file:///C:/Meus Documentos/Minha Pasta/Subpasta/MinhaPlanilha.odt e por esse motive inserimos a função TranformaDeCaminhoParaURL. Veja a sua declaração em nosso pequeno sistema:
function TForm1.TranformaDeCaminhoParaURL(nomeArq: String): String;
var
NomeFile : String;
begin
NomeFile := LowerCase(nomeArq);
if (Pos('file:///', NomeFile) = 0) then
result := 'file:///' + StringReplace(NomeFile, '\', '/', [rfReplaceAll, rfIgnoreCase]);
end;
Deixo na sua responsabilidade de fazer as verificações da existência do arquivo e da pasta. Não irei tratar de detalhes reais de um programa. Como falei, para que você salve um arquivo do Calc é necessário alterar a formato de definição do caminho. O BrOffice sempre passa a idéia para esse tipo de coisa como se fosse um endereço URL, logo, sempre que vocês ver URL em um parâmetro já saberá o que mais ou menos está sendo exigido.
Sigamos agora para os eventos do segundo botão.
procedure TForm1.Button2Click(Sender: TObject);
var
Valores : Variant;
Destino : String;
begin
Destino := TranformaDeCaminhoParaURL(Edit1.Text);
Valores := VarArrayCreate([0,0], varVariant);
Valores[0] := AtribuirValores('Overwrite',true);
Destino := Destino + '.ods'; //Extensão da planilha do broffice
Documento.storeAsURL(Destino, Valores);
end;
A variável
Valores é muito interessante e ela lhe dará acesso a um grande universo; essa variável ela faz referência a dois parâmetros – um chamado
Name e outro chamado
Value. Passa a idéia de um array multidimensional, algo como
Teste[0][0] e
Teste[0][1], a função
VarArrayCreate cria um array de variantes, sendo então o primeiro parâmetro o tamanho do array e o segundo, o tipo de valores registrados no array. Se você usar VarArrayCreate([0, 4], varInteger) estará fazendo uma referência a algo assim:
Elementos := VarArrayCreate([0,4], varInteger);
Elementos[0] := 1;
Elementos[1] := 2;
Elementos[2] := 100;
Elementos[3] := 1000;
Elementos[4] := 10000;
O que foi feito então em nosso botão: Criamos o array e informamos que ele conterá um único valor. Na sequência temos a seguinte declaração:
Valores[0] := AtribuirValores('Overwrite', true); Essa função também foi criada e adicionada no parte inicial do nosso pequeno programa, e está registrada da seguinte forma:
function TForm1.AtribuirValores(Nome, Valor : Variant): Variant;
var
Reflec : Variant;
begin
Reflec := BrOffice.createInstance('com.sun.star.reflection.CoreReflection');
Reflec.forName('com.sun.star.beans.PropertyValue').createObject(result);
result.Name := Nome;
result.Value:= Valor;
end;
Essa função não foi criada por mim, mas está presente naquele documento menciaonado em nossa primeira lição. Essa função cria uma instância do Core do BrOffice e atribuir propriedades de valor. Você usará muito essa função, porque podemos atribuir os elementos de formatação de células e até mesmo salvar arquivos usando a estrutura
UNO que veremos mais adiante. Ao usarmos a função, atente que estamos definindo a atribuição de propriedades para o elemento
ZERO – Valores
[0] e estamos dizendo o seguinte Valores[0][Name] := 'Overwrite' e Valores[0][Value] := true; Veja que isso é somente uma representação. Isto feito, avançamos para o procedimento
storeAsUrl(URL, Array); e fizemos então:
Documento.storeAsURL(Destino, Valores);
Salva o documento na pasta especificada e dentro daquele padrão que modificamos e exigido pelo BrOffice. E então o array chamado Valores e dizendo que se existir um arquivo com o mesmo nome no local que estamos salvando ele será sobreescrito. O recomendável é sempre fazer
AtribuirValores('Overwrite', false). Isso é o recomendável.
Um pequeno detalhe, estamos trabalhando com arquivos do tipo BrOffice, então adicionei ao endereço a extensão para o arquivo – tipo '.ODS' que é o padrão de extensão.
Download
O código fonte se encontra anexado a este artigo. Baixe-o se achar necessário.\
Delphi e BrOffice - Parte 2.rar
Até o próximo passo!