• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

heldercorreia

[Resolvido]Função que escreve fórmula cujas variáveis são resultados intermédios

10 mensagens neste tópico

Private Function calc_motor(p, a, b, c, d) 'Escreve na folha de cálculo os resultados dos cálculos
                               'da impedância relativa ao motor
     Cells(Range(p).Row, Range(p).Column).Value = "ZM ="
    Cells(Range(p).Row + 1, Range(p).Column).Value = "XM ="
    Cells(Range(p).Row + 2, Range(p).Column).Value = "RM ="
    Sheet2.Range(Cells(Range(p).Row + 2, Range(p).Column + 1), p).HorizontalAlignment = xlRight
    
    Cells(Range(p).Row, Range(p).Column + 1).formula = a*b^2
    Cells(Range(p).Row + 1, Range(p).Column + 1).formula = c^2*d
'Na célula seguinte gostaria que ficasse a fórmula relativa à soma das duas células anteriores
    Cells(Range(p).Row + 2, Range(p).Column + 1).formula = Cells(Range(p).Row, Range(p).Column + 1)+Cells(Range(p).Row + 1, Range(p).Column + 1)

End Function

E é assim... a vida! ( de quem sabe pouco ) Deu para perceber a ideia?

Se fosse para apresentar apenas os resultados, utilizava variáveis dentro da própria função, mas é importante que fique a fórmula..

É possível concretizar algo desse tipo?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O problema é que a função formula funciona se for uma formula directa, ou seja =A1+A2. Mas se for só pelos valores das referencias não dá.

Para conseguires o que pretendes tens de usar outra função:

Cells(Range(p).Row + 2, Range(p).Column + 1).FormulaR1C1 = "=R"+ cstr(Range(p).Row) + "C" + cstr(Range(p).Column + 1)+"R" + cstr(Range(p).Row + 1) + "C" + cstr(Range(p).Column + 1)

O R significa que o valor que vem a seguir será o valor de referencia da Row e C o da column. por exemplo "=R5C1" é o valor da 5ª linha da primeira coluna. Ou como quem diz, =A5

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não consigo solucionar esta questão, creio que o problema está na passagem de argumentos

Chamo a função com:

call calc_motor("s25", "s4", "s5", "s6", "s7")

Assim, eles estão a ser passados como strings, ok. Há integers, booleans, etc, não há um tipo Célula? O problema pode vir daqui :\

Com esta função, o objectivo era poder ter vários motores, ou seja, em qualquer lado que quiser, basta chamar a função com argumentos diferentes, e os cálculos são apresentados na primeira célula passada em argumento, sendo as váriáveis os argumentos seguintes. Podia fazer call calc_motor("t25", "t8", "x9", "y10", "z11") e assim por diante..

o problema está depois em

Private Function calc_motor(p, a, b, c, d)
   Cells(Range(p).Row, Range(p).Column).Value = "ZM ="
   Cells(Range(p).Row + 1, Range(p).Column).Value = "XM ="
   Cells(Range(p).Row + 2, Range(p).Column).Value = "RM ="

   Cells(Range(p).Row, Range(p).Column + 1).formula = a*b^2
   Cells(Range(p).Row + 1, Range(p).Column + 1).formula = c^2*d
   Cells(Range(p).Row + 2, Range(p).Column + 1).FormulaR1C1 = "=R"+ cstr(Range(p).Row) + "C" + cstr(Range(p).Column + 1)+"R" + cstr(Range(p).Row + 1) + "C" + cstr(Range(p).Column + 1)

End Function

Onde nem sequer consigo fazer funcionar as primeiras duas funções.. Como é que se podem multiplicar strings né? É natural que dê erro..

Tentei fazer

a=range(a)
b=range(b)
..

mas apenas coloca o .value em a,b,c.. e eu precisava mesmo que ficassem lá as formulas, porque uma vez que a fórmula já lá está preenchida, pode-se depois mudar as vaiáveis e assim o resultado muda também.

Nem sei se me conseguir fazer entender bem, quanto mais conseguir este feito :rant_01:

Depois acho que conseguia fazer uma função que me retornasse baseado numa célula e um determinado offset para usar nas fórmulas que requerem resultados intermédios, porque em alguns casos tenho fórmulas extensas e com o método do MetalFatigue ficam muitissimo mais complicadas e assim aproveitava a ideia dele.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Nem sei se me conseguir fazer entender bem, quanto mais conseguir este feito  :rant_01:

Infelizmente, nem por isso.

Não tinha compreendido bem o teu problema. Pensava que a,b,c,d fossem valores. Continuo a não entender o objectivo final. Se pudesses dar um exemplo seria mais fácil.

Assim, eles estão a ser passados como strings, ok. Há integers, booleans, etc, não há um tipo Célula? O problema pode vir daqui :\

As celulas são do tipo Range. Um exemplo para perceberes isto será range("A1"). Ou seja Range sabes que é um tipo Range. sendo que só tem um endereço, sabes então que se trata de uma célula.

Ok, agora indo ao teu problema. Há várias formas de o atacar pelo que entendi do que pretendes (sem conhecer bem o objectivo final).

1º Podes passar os argumentos como celulas, ou seja como te expliquei usando o range:

call calc_motor(range("s25"), range("s4"), range("s5"), range("s6"), range("s7"))

2º Pelo que entendi tens formulas em todas as variáveis excepto na "S25", que serve de referencia. podes passar já as formulas:

call calc_motor(range("s25").Formula, range("s4").Formula, range("s5").Formula, range("s6").Formula, range("s7").Formula)

3º Fazer como estás a fazer:

call calc_motor("s25", "s4", "s5", "s6", "s7")

A meu ver a 1ª é a melhor e a forma mais lógica de o fazeres. Mas se entenderes de outra forma...cada um tem a sua maneira de programar.

Usando a 1ª, terias o seguinte procedimento (já agora não tem lógica ser uma Function se não devolve nada):

Private Sub calc_motor(p, a, b, c, d) 
    'estas 3 julgo serem meramente indicativas do que se trata a função ao lado. Se não for explica-me sff 
    Cells(Range(p).Row, Range(p).Column).Value = "ZM ="
    Cells(Range(p).Row + 1, Range(p).Column).Value = "XM ="
    Cells(Range(p).Row + 2, Range(p).Column).Value = "RM ="

    Cells(p.Row, p.Column + 1).formula = a.Formula & "*" & Right(b.Formula,Len(b.Formula)-1) & "^2"
    Cells(p.Row + 1, p.Column + 1).formula = c.Formula & "^2*" & right(d.Formula, Len(d.Formula)-1)

'Para se tornar mais legivel irei criar 2 variaveis que guardam exactamente as celulas que acabamos de colocar as formulas

dim x as range, y as range

x = Cells(p.Row, p.Column + 1)
y = Cells(p.Row + 1, p.Column + 1)

    Cells(p.Row + 2, p.Column + 1).Formula = x.Formula & right (y.Formula, Len(y.Formula)-1)

End Sub

Isto foi tudo sem criar um caso por isso não foi testado. No entanto julgo que irá funcionar se o raciocinio de que as variáveis (a,b,c,d) são referencias a células com formulas.

Explicando o código:

Tendo passado como células as variáveis funcionam como tal. Logo todas as funcionalidades associadas a uma Celula (range) é possível. Julgo que esta parte está simples de entender.

Ora o que define para o excel se o que vem a seguir é uma formula é o "=". Quando escreves a.Formula ele passa igualmente o =. Isto tudo vai do tipo string. Ora quando vais adicionar b ele vai passar também com o =. Então precisas de te livrar dele senão ficava algo do genero "=A1*B1+=A2*B2", o que iria dar erro. Logo há que dizer que queres tudo menos o 1º caracter (=).

É preciso entender que estás sempre a trabalhar com strings, por isso termos de colocar sempre aspas nos sinais e valores. Tudo é passado como texto, mas como tem o = antes ele vai perceber que se trata de uma formula.

Espero que tenha ajudado. Dá noticias :P

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Já vi o teu ficheiro. A minha primeira solução (do 1º post) iria funcionar. No entanto compreendo que se tornava algo extensa e complicada.

Seja como for a teu pensamento inicial estava correcto excepto numa coisa. E eu também deveria ter reparado nisso, porque faltava lá umas coisas.

Vou só colocar a 1ª formula, que percebes logo como fazer o resto:

Cells(Range(p).Row, Range(p).Column + 1).Formula = "=" & a & "*" & b & "^2"

Como te disse as formulas são passadas como texto e necessitam de lá colocar o igual também. Era na verdade bastante simples e eu só estava a complicar...lol

Eu não entendo nada de circuitos e aquelas siglas é tipo chinês para mim. No entanto parece-me porreira a ideia. As pessoas sentem-se mais a vontade a mexer no excel do que se for mesmo um programa.

Detectei no entanto alguns problemas ligeiros. 1º só a nível estético se se escolher no C, transf o desenho fica a frente do T2. Uma mariquice eu sei...

o 2º foi que consegui despoletar um erro. Sendo um completo ignorante no assunto escolhi obviamente coisas ao calhas o que provocou num dos cálculos do código a tentativa de fazer uma raiz quadrada de um numero negativo. Devias arranjar um mecanismo do programa se precaver destes erros. Error handling em VBA não é grande coisa mas é possível, ou com If ou While para obrigar o utilizador a escolher dentro de um determinado intervalo ou através do On Error GoTo ErroX.

Força aí e boa sorte :thumbsup:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
Detectei no entanto alguns problemas ligeiros. 1º só a nível estético se se escolher no C, transf o desenho fica a frente do T2. Uma mariquice eu sei...

Não senhor, muito bem visto..

Já consegui que aparecesse na célula o resultado, e por trás está a fórmula em valores numéricos:

=1/8*400^2/20000 e dá o respectivo valor, para começo  já se estão as coisas a compor!

Agora, o que era importante, era que no lugar dos valores ficassem as células, ou seja:

=1/A1*A2^2/A3

Para que no excel possa ir a essas células, mudar o seu valor e consequentemente mudar também o resultado... no VBA é só para escrever as formulas nas células..

Isto porque, se apresentasse somente os resultados, era preciso refazer toda a simulação e obter novos resultados.. Se funcionasse como eu imagino, o utilizador podia ir mudando os valores 'em directo' era ouro sobre azul..

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O facto de me aparecerem os valores contidos nas células ao invés das próprias células devia-se ao facto de não ter alterado o modo como chamo a função, tinha

Call calc_motor("r25", Range("s4"), Range("s5"), Range("s6"), Range("s7"))

Alterando para

Call calc_motor("r25", "s4", "s5", "s6", "s7")

Aparece-me na célula: =1/'s6'*'s4'^2/'s5'

Também não funciona devido às plicas..

Quanto ao que mencionaste de aparecer raiz de um número negativo, tem mesmo que ser.. creio que me basta fazer uma função que calcule a raiz do módulo e depois colocar o 'i' de numero imaginário, isto se não houver já função que o faça.

Edit: entretanto, resolvi a questão das plicas.

as duas primeiras células já apresentam as fórmulas correctas, as quais dependem apenas das variáveis passadas em argumento. Para a última célula continuo sem conseguir utilizar as suas duas células anteriores como variáveis na sua fórmula.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Solucionei com

Range(p).Offset(x, y).Address

Sendo que o endereço retornado fica a fazer parte da string que constitui a fórmula.

Estranho é o facto de na célula a fórmula conter inicialmente erro, dou dupli clique nela para ver a fórmula, aparentemente tudo bem.. dou enter e magicamente desaparece o erro e aparece o valor certinho...

btw, para onde é que fugiu o 'Topic Solved' ?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Ainda bem que já resolveste ;)

Desculpa não ter te ajudado mais, mas não tenho cá vindo.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não tens que pedir desculpa, eu é que agradeço as respostas ;)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora