Fechar Planilha via Macro - erros

Olá comunidade.
Tenho um modelo de planilha de uso frequente. Este modelo NÃO deve ser alterado pelo usuário comum.
Preenchidos os dados, o usuário deverá gerar um arquivo (cópia) SECUNDÁRIO. Ou até, mais que um arquivo secundário na mesma leva de operações.
Depois de concluída a tarefa, deve fechar o ARQUIVO BASE, SEM SALVAR as alterações:

Para isso usei o seguinte código (que já fica aqui para quem precisar):

' Obtém a Pasta e Arquivo atuais
AbaDados = Doc.Sheets.getByName("Dados")
Pasta = AbaDados.getCellRangeByName("B7").String
If Pasta = "" then
	Dim Atributo
	GlobalScope.BasicLibraries.LoadLibrary("Tools")
	Atributo() = Doc.getArgs()
	Past0 = DirectoryNameoutofPath( Atributo(0).Value , "/")
	Pasta = ConvertFromUrl (Past0) & "\"
	End If
Pasta = InputBox ( "Informe a Pasta para salvamento" , "Algoritmos JEDI" , Pasta)
If Pasta = "" then : Exit Sub : End If
If Mid(Pasta, Len(Pasta)) <> "\" then
	Pasta = Pasta & "\"
	End If
' Obtém o nome do arquivo	
Arq = AbaDados.getCellRangeByName("B8").String
If Arq = "" then
	Fram = Doc.CurrentController.Frame.Title()
	Arq = Left(Fram , InStr(Fram, ".ods") + 3 )
	End If
Arq = InputBox ( "Informe o nome do Arquivo" , "Algoritmos JEDI" , Arq)
If Arq = "" then : Exit Sub
	ElseIf InStr(Arq, ".ods") = False Then
	Arq = Arq & ".ods"
	End If

' Grava em DADOS a identificação do arquivo
AbaDados.getCellRangeByName("B7").String = Pasta
AbaDados.getCellRangeByName("B8").String = Arq

' Grava um arquivo com o nome indicado
NArq = ConvertToUrl( Pasta & Arq)

    Dim Args As New com.sun.star.beans.PropertyValue
    Args.Name = "FilterName"
    Args.Value = "Calc8"
    Doc.StoreToUrl(NArq , Array(Args()) )
    
    Fechar = MsgBox ("O novo arquivo " & uCase(Arq) & CHR(10) & _
           	"foi gravado na pasta " & CHR(10) & _
            Pasta & CHR(10) & _
            "Deseja fechar o presente arquivo-base? " & CHR(10) _
            , 48 , "Algoritmos  JEDI")

E aqui começam os problemas. Sei que é um problema já conhecido. Porém, pode ser que alguém tenha encontrado uma solução.
Para fechar o arquivo usei inicialmente esse código:
Primeira tentativa:

If Fechar = 6 then : ThisComponent.close(true) : End If

Quando uso isso em um Módulo diferente do restante do código, funciona bem.
Mas obviamente esta solução seria um “remendo” grosseiro que gostaria de evitar.
Quando ele está incorporado no módulo do conjunto, com as outras MACROS usadas no sistema, dá ERRO GRAVE (Fecha o LO com aviso de recuperação. Ao abrir de novo o LO, entra em um LOOP, sendo necessário CTRL+ALT+DEL para “finalizar” artificialmente a execução).

Tentei fazer isso (Segunda tentativa):

If Fechar = 6 then'
	If HasUnoInterfaces(Doc, "com.sun.star.util.XCloseable") Then
 		ThisComponent.close(true)
		Else
 		ThisComponent.dispose()
		End If
End If

E também isso (Terceira tentativa):

If Fechar = 6 then'
	If HasUnoInterfaces(Doc, "com.sun.star.util.XCloseable") Then
 		ThisComponent.close(true)
		Else
 		ThisComponent.dispose()
		End If
	stardesktop.terminate
End If

E, por fim, recorri às chamadas UNO (que queria evitar) - Quarta tentativa:

If Fechar = 6 then
	Ctrl = ThisComponent.CurrentController.Frame
	Servico = createUnoService("com.sun.star.frame.DispatchHelper")
	Servico.executeDispatch(Ctrl, ".uno:CloseDoc", "", 0, Array())
End If

Isso até (meio que) funcionou. Com o inconveniente de perguntar para o usuário se deseja FECHAR SEM SALVAR, o que gera alguma confusão, pois alguém inexperiente poderá supor que perderá os arquivos SECUNDÁRIOS que criou. Além disso, corre-se o risco de, por erro, o usuário salvar as alterações NO ARQUIVO BASE, comprometendo futuras operações.
Porém, se houver alguma outra planilha aberta no momento (o que é bem comum no nosso caso), ocorrerá aquele ERRO GRAVE também.

Alguém sabe a solução?

1 Like

ATUALIZAÇÃO (Progresso do estudo):

Acho que descobri a origem do problema, mas ainda não sei como resolvê-lo.
Observei que:

  1. O erro acontece quando a função que fecha o arquivo está inserida no MODULO principal de comandos . Se for colocado em um módulo separado, funciona;

  2. se, no momento em que a Função é executada, o arquivo a ser fechado é o único aberto, o erro não acontece.

  3. Em outra Função que fecha arquivo, no mesmo módulo principal, o erro não acontece, independente de haver ou não outros arquivos CALC abertos no momento.

Partindo disso:

a) inseri condição para que, sempre que houver outras abas CALC abertas, o foco seja alterado para um desses FRAMEs, antes de fechar o arquivo desejado.
b) Alterei o flag MODIFIED dele para FALSE, a fim de desviar da pergunta sobre gravar alterações antes de fechar.

Feito isso, percebi que a CAIXA DE DIÁLOGO que chama a função permanecia aberta e estimo que seja por isso que ocorre o erro. Só que … (prossegue)

… Só que não entendo porque isso acontece, já que houve a seleção da função com a coleta dos dados respectivos, o que, normalmente, fecharia a Caixa.

Alguém sabe algo a respeito disso?

@Jedison, segue a macro: ( nesta só pega a Pasta e o Nome do arquivo e Salva Como )

Como o meu arquivo a geração de Nome e Pasta são automáticos, não coloquei averiguação se campos estão vazios.

Sub SalvarProposta
' PEGAR NOME PASTA
	CELL_PASTA = "Planilha1.F2"
    FOLDER = ThisComponent.CurrentController.ActiveSheet.getCellRangeByName(CELL_PASTA)
' PEGAR NOME ARQUIVO 
    CELL_ARQ = "Planilha1.D8"
    ARQ = ThisComponent.CurrentController.ActiveSheet.getCellRangeByName(CELL_ARQ)
' SALVAR COMO
    path = ConvertToURL(FOLDER.String + ARQ.String + ".ods")
Dim args1(1) as new com.sun.star.beans.PropertyValue
args1(0).Name = "URL"
args1(0).Value = path 'DirFile 
args1(1).Name = "FilterName"
args1(1).Value = "calc8"
CreateUnoService("com.sun.star.frame.DispatchHelper") _
.executeDispatch(ThisComponent.CurrentController _
.Frame, ".uno:SaveAs", "", 0, args1())
End Sub 

Arquivo do teste

Oi Schiavinato.

Obrigado pelo empenho. Mas essa parte pra mim tá sem problemas. A minha verdadeira questão é mesmo FECHAR o CALC depois de terminar a operação sem que ocorram os erros. Quando coloco essa operação em um MÓDULO isolado, fecha tranquilinho, sem problema nenhum. Mas quando coloco o código no módulo do sistema (junto com os outros comandos), dá aquele erro infernal.

Tenho este comando que fecha sem salvar e não pergunta nada:

ThisComponent.Close(true)

Sim. Foi a minha primeira tentativa. Não dá certo, nas condições que referi.

Poste a macro completa.

A opção de “Salvar Como” por meio de rotina UNO não me é atrativa, pois para isso há um botão que executa a operação direto na Barra de Ferramentas. Então, não dificilmente haveria uma razão para colocar essa função em uma Macro. Pelo menos no meu caso, em que as barras originais do CALC permanecem visíveis e, inclusive, costuma trazer tb essa específica, para o lado do SALVAR.

Ola @Jedison, a macro acima usa Salvar como com base em informações “voláteis” da planilha, repare que ela busca a PASTA e o ARQUIVO, é útil, por exemplo, quando salva arquivos com o nome a quem foi endereçado uma proposta/orçamento.

Ah, entendi. Perfeito.
Não é o meu caso todavia.
Na minha, usei aquele recurso para permitir que nos próximos arquivos, depois de gravado um a partir do modelo, aos demais seja facilitada a definição do nome. É que no meu caso é comum a criação de arquivos múltiplos referentes ao mesmo bloco de dados.

Olá, tem o seguinte código colocando “Option VBASupport 1” em cima da Sub FecharSemSalvar. Esse código fecha o aplicativo sem exibir a mensagem: Deseja Salvar o Documento. Insiro um módulo para as macros com suporte em VBA e coloco Option VBASupport 1 no começo deste.

Option VBASupport 1

Sub FecharSemSalvar
Dim oDoc as Object
oDoc = ThisComponent
If HasUnoInterfaces(oDoc,“com.sun.star.util.XCloseable”) Then
oDoc.close(True)
Stop
Else
oDoc.dispose()
End If
End Sub

Oi Ronaldo.
Obrigado pela contribuição. Porém. não mudou nada.

Olá comunidade.

Volto com ótimas notícias. Depois de muitas tentativas e estudo do funcionamento das macros e caixas de diálogo, finalmente encontrei a solução.

Como mencionei nos comentários (complementos) anteriores, o problema era que quando se executa um formulário, mesmo depois de sair dele, por algum motivo (que suponho seja um erro do Sistema LibreOffice - Basic, já que não encontrei justificativa para ser assim), em alguns casos (que não cabe aqui discorrer) ele permanece ativo.

Assim, quando se fecha o documento [ ThisComponent.Close(False) ] ocorre o erro, pois a interface do LibreOffice permanece em execução, sem encerrar o processo na bandeja do Windows. Foi táo difícil encontrar o erro porque ele acontece somente mediante condições específicas.

Enfim: Para que isso não ocorra, antes do CLOSE, deve-se dispensar qualquer formulário que esteja ativo. Aliás, isso pode ser feito assim que se colhe todas as informações advindas dele. Algo do tipo

Form.Dispose()

Questão acessória que surgiu durante o estudo, foi a referente à indesejável pergunta sobre salvar o arquivo antes do fechamento. No caso em estudo, a operação ocorre em um arquivo padrão que não deve ser alterado. Para que isso não ocorra, basta excluir o FLAG de alteração (que o LO coloca automaticamente sempre que se altera um documento) antes de fechar:

ThisComponent.Modified = False

Obrigado a todos pelas colaborações.