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

Sign in to follow this  
heldercorreia

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

Recommended Posts

heldercorreia

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?

Share this post


Link to post
Share on other sites
MetalFatigue

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

Share this post


Link to post
Share on other sites
heldercorreia

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 😡

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.

Share this post


Link to post
Share on other sites
MetalFatigue

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

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

Share this post


Link to post
Share on other sites
MetalFatigue

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:

Share this post


Link to post
Share on other sites
heldercorreia
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..

Share this post


Link to post
Share on other sites
heldercorreia

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.

Share this post


Link to post
Share on other sites
heldercorreia

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' ?

Share this post


Link to post
Share on other sites
MetalFatigue

Ainda bem que já resolveste ;)

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

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.