Olá pessoal…
Na vídeo aula de hoje, vou mostrar como fazer abas (folders) em MVC.
Abaixo o código do exemplo 1 (Pai e Filhos):
//Bibliotecas #Include 'Protheus.ch' #Include 'FWMVCDef.ch' //Variáveis Estáticas Static cTitulo := "Grp. Produtos (Abas)" /*/{Protheus.doc} zAba1 Exemplo de rotina com multiplas abas em MVC @author Atilio @since 25/07/2017 @version 1.0 @return Nil, Função não tem retorno @example u_zAba1() /*/ User Function zAba1() Local aArea := GetArea() Local oBrowse Local cFunBkp := FunName() SetFunName("zAba1") //Instânciando FWMBrowse oBrowse := FWMBrowse():New() oBrowse:SetAlias("SBM") oBrowse:SetDescription(cTitulo) oBrowse:Activate() SetFunName(cFunBkp) RestArea(aArea) Return Nil /*---------------------------------------------------------------------* | Func: MenuDef | | Desc: Criação do menu MVC | *---------------------------------------------------------------------*/ Static Function MenuDef() Local aRot := {} //Adicionando opções ADD OPTION aRot TITLE 'Visualizar' ACTION 'VIEWDEF.zAba1' OPERATION MODEL_OPERATION_VIEW ACCESS 0 //OPERATION 1 Return aRot /*---------------------------------------------------------------------* | Func: ModelDef | | Desc: Criação do modelo de dados MVC | *---------------------------------------------------------------------*/ Static Function ModelDef() Local oModel := Nil Local oStPai := FWFormStruct(1, 'SBM') Local oStFilho1 := FWFormStruct(1, 'SB1') Local oStFilho2 := FWFormStruct(1, 'SB1') Local aRelFilho1 := {} Local aRelFilho2 := {} //Criando o modelo oModel := MPFormModel():New('zAba1M') oModel:AddFields('SBM_MASTER', /*cOwner*/, oStPai) //Criando as grids dos filhos oModel:AddGrid('SB1_FILHO1', 'SBM_MASTER', oStFilho1) oModel:AddGrid('SB1_FILHO2', 'SBM_MASTER', oStFilho2) //Criando os relacionamentos dos pais e filhos aAdd(aRelFilho1, {'B1_FILIAL', 'BM_FILIAL'}) aAdd(aRelFilho1, {'B1_GRUPO', 'BM_GRUPO'}) aAdd(aRelFilho1, {'B1_LOCPAD', '00'}) aAdd(aRelFilho2, {'B1_FILIAL', 'BM_FILIAL'}) aAdd(aRelFilho2, {'B1_GRUPO', 'BM_GRUPO'}) aAdd(aRelFilho2, {'B1_LOCPAD', '01'}) //Criando o relacionamento do Filho 1 oModel:SetRelation('SB1_FILHO1', aRelFilho1, SB1->(IndexKey(1))) oModel:GetModel('SB1_FILHO1'):SetUniqueLine({"B1_FILIAL","B1_COD"}) //Criando o relacionamento do Filho 2 oModel:SetRelation('SB1_FILHO2', aRelFilho2, SB1->(IndexKey(1))) oModel:GetModel('SB1_FILHO2'):SetUniqueLine({"B1_FILIAL","B1_COD"}) //Finaliznado a criação do Model oModel:SetPrimaryKey({}) oModel:SetDescription("Grupo de Produtos - com Abas") oModel:GetModel('SBM_MASTER'):SetDescription('Modelo Grupo') oModel:GetModel('SB1_FILHO1'):SetDescription('Modelo Prod. Arm. 00') oModel:GetModel('SB1_FILHO2'):SetDescription('Modelo Prod. Arm. 01') Return oModel /*---------------------------------------------------------------------* | Func: ViewDef | | Desc: Criação da visão MVC | *---------------------------------------------------------------------*/ Static Function ViewDef() Local oView := Nil Local oModel := FWLoadModel('zAba1') Local oStPai := FWFormStruct(2, 'SBM') Local oStFilho1 := FWFormStruct(2, 'SB1') Local oStFilho2 := FWFormStruct(2, 'SB1') //Criando a View oView := FWFormView():New() oView:SetModel(oModel) //Adicionando os campos do cabeçalho oView:AddField('VIEW_SBM', oStPai, 'SBM_MASTER') //Grids dos filhos oView:AddGrid('VIEW_FILHO1', oStFilho1, 'SB1_FILHO1') oView:AddGrid('VIEW_FILHO2', oStFilho2, 'SB1_FILHO2') //Setando o dimensionamento de tamanho oView:CreateHorizontalBox('SUPERIOR', 30) oView:CreateHorizontalBox('INFERIOR', 70) //Criando a folder dos produtos (filhos) oView:CreateFolder('PASTA_FILHOS', 'INFERIOR') oView:AddSheet('PASTA_FILHOS', 'ABA_FILHO01', "Armazém 00") oView:AddSheet('PASTA_FILHOS', 'ABA_FILHO02', "Armazém 01") //Criando os vinculos onde serão mostrado os dados oView:CreateHorizontalBox('ITENS_FILHO01', 100,,, 'PASTA_FILHOS', 'ABA_FILHO01' ) oView:CreateHorizontalBox('ITENS_FILHO02', 100,,, 'PASTA_FILHOS', 'ABA_FILHO02' ) //Amarrando a view com as box oView:SetOwnerView('VIEW_SBM', 'SUPERIOR') oView:SetOwnerView('VIEW_FILHO1', 'ITENS_FILHO01') oView:SetOwnerView('VIEW_FILHO2', 'ITENS_FILHO02') Return oView
Abaixo o código do exemplo 2 (Pai, Filhos e Netos):
//Bibliotecas #Include 'Protheus.ch' #Include 'FWMVCDef.ch' //Variáveis Estáticas Static cTitulo := "Grp. Produtos (Abas)" /*/{Protheus.doc} zAba2 Exemplo de rotina com multiplas abas em MVC @author Atilio @since 25/07/2017 @version 1.0 @return Nil, Função não tem retorno @example u_zAba2() /*/ User Function zAba2() Local aArea := GetArea() Local oBrowse Local cFunBkp := FunName() SetFunName("zAba2") //Instânciando FWMBrowse oBrowse := FWMBrowse():New() oBrowse:SetAlias("SBM") oBrowse:SetDescription(cTitulo) oBrowse:Activate() SetFunName(cFunBkp) RestArea(aArea) Return Nil /*---------------------------------------------------------------------* | Func: MenuDef | | Desc: Criação do menu MVC | *---------------------------------------------------------------------*/ Static Function MenuDef() Local aRot := {} //Adicionando opções ADD OPTION aRot TITLE 'Visualizar' ACTION 'VIEWDEF.zAba2' OPERATION MODEL_OPERATION_VIEW ACCESS 0 Return aRot /*---------------------------------------------------------------------* | Func: ModelDef | | Desc: Criação do modelo de dados MVC | *---------------------------------------------------------------------*/ Static Function ModelDef() Local oModel := Nil Local oStPai := FWFormStruct(1, 'SBM') Local oStFilho1 := FWFormStruct(1, 'SB1') Local oStFilho2 := FWFormStruct(1, 'SB1') Local oStNeto1a := FWFormStruct(1, 'SD1') Local oStNeto1b := FWFormStruct(1, 'SC7') Local oStNeto2a := FWFormStruct(1, 'SD1') Local oStNeto2b := FWFormStruct(1, 'SC7') Local aRelFilho1 := {} Local aRelFilho2 := {} Local aRelNeto1a := {} Local aRelNeto1b := {} Local aRelNeto2a := {} Local aRelNeto2b := {} //Criando o modelo oModel := MPFormModel():New('zAba2M') oModel:AddFields('SBM_MASTER', /*cOwner*/, oStPai) //Criando as grids dos filhos oModel:AddGrid('SB1_FILHO1', 'SBM_MASTER', oStFilho1) oModel:AddGrid('SB1_FILHO2', 'SBM_MASTER', oStFilho2) //Criando as grids dos netos oModel:AddGrid('SD1_NETO1A', 'SB1_FILHO1', oStNeto1a) oModel:AddGrid('SC7_NETO1B', 'SB1_FILHO1', oStNeto1b) oModel:AddGrid('SD1_NETO2A', 'SB1_FILHO2', oStNeto2a) oModel:AddGrid('SC7_NETO2B', 'SB1_FILHO2', oStNeto2b) //Criando os relacionamentos dos pais e filhos aAdd(aRelFilho1, {'B1_GRUPO', 'BM_GRUPO'}) aAdd(aRelFilho1, {'B1_LOCPAD', '00'}) aAdd(aRelFilho2, {'B1_GRUPO', 'BM_GRUPO'}) aAdd(aRelFilho2, {'B1_LOCPAD', '01'}) //Criando os relacionamentos dos netos com os filhos aAdd(aRelNeto1a, {'D1_COD', "oModel:GetModel('SB1_FILHO1'):GetValue('B1_COD')"}) aAdd(aRelNeto1a, {'D1_LOCAL', "oModel:GetModel('SB1_FILHO1'):GetValue('B1_LOCPAD')"}) aAdd(aRelNeto1b, {'C7_PRODUTO', "oModel:GetModel('SB1_FILHO1'):GetValue('B1_COD')"}) aAdd(aRelNeto1b, {'C7_LOCAL', "oModel:GetModel('SB1_FILHO1'):GetValue('B1_LOCPAD')"}) aAdd(aRelNeto2a, {'D1_COD', "oModel:GetModel('SB1_FILHO2'):GetValue('B1_COD')"}) aAdd(aRelNeto2a, {'D1_LOCAL', "oModel:GetModel('SB1_FILHO2'):GetValue('B1_LOCPAD')"}) aAdd(aRelNeto2b, {'C7_PRODUTO', "oModel:GetModel('SB1_FILHO2'):GetValue('B1_COD')"}) aAdd(aRelNeto2b, {'C7_LOCAL', "oModel:GetModel('SB1_FILHO2'):GetValue('B1_LOCPAD')"}) //Criando o relacionamento do Filho 1 - Produtos do Armazém 00 oModel:SetRelation('SB1_FILHO1', aRelFilho1, SB1->(IndexKey(1))) oModel:GetModel('SB1_FILHO1'):SetUniqueLine({"B1_FILIAL", "B1_COD"}) //Criando o relacionamento dos netos do Filho 1 oModel:SetRelation('SD1_NETO1A', aRelNeto1a, SD1->(IndexKey(1))) oModel:GetModel('SD1_NETO1A'):SetUniqueLine({"D1_FILIAL", "D1_DOC", "D1_SERIE", "D1_ITEM", "D1_COD"}) oModel:SetRelation('SC7_NETO1B', aRelNeto1b, SC7->(IndexKey(1))) oModel:GetModel('SC7_NETO1B'):SetUniqueLine({"C7_FILIAL", "C7_ITEM", "C7_PRODUTO"}) //Criando o relacionamento do Filho 2 - Produtos do Armazém 01 oModel:SetRelation('SB1_FILHO2', aRelFilho2, SB1->(IndexKey(1))) oModel:GetModel('SB1_FILHO2'):SetUniqueLine({"B1_FILIAL", "B1_COD"}) //Criando o relacionamento dos netos do Filho 2 oModel:SetRelation('SD1_NETO2A', aRelNeto2a, SD1->(IndexKey(1))) oModel:GetModel('SD1_NETO2A'):SetUniqueLine({"D1_FILIAL", "D1_DOC", "D1_SERIE", "D1_ITEM", "D1_COD"}) oModel:SetRelation('SC7_NETO2B', aRelNeto2b, SC7->(IndexKey(1))) oModel:GetModel('SC7_NETO2B'):SetUniqueLine({"C7_FILIAL", "C7_ITEM", "C7_PRODUTO"}) //Finalizando a criação do Model oModel:SetPrimaryKey({}) oModel:SetDescription("Grupo de Produtos - com Abas") oModel:GetModel('SBM_MASTER'):SetDescription('Modelo Grupo') oModel:GetModel('SB1_FILHO1'):SetDescription('Modelo Prod. Arm. 00') oModel:GetModel('SB1_FILHO2'):SetDescription('Modelo Prod. Arm. 01') Return oModel /*---------------------------------------------------------------------* | Func: ViewDef | | Desc: Criação da visão MVC | *---------------------------------------------------------------------*/ Static Function ViewDef() Local oView := Nil Local oModel := FWLoadModel('zAba2') Local oStPai := FWFormStruct(2, 'SBM') Local oStFilho1 := FWFormStruct(2, 'SB1') Local oStFilho2 := FWFormStruct(2, 'SB1') Local oStNeto1a := FWFormStruct(2, 'SD1') Local oStNeto1b := FWFormStruct(2, 'SC7') Local oStNeto2a := FWFormStruct(2, 'SD1') Local oStNeto2b := FWFormStruct(2, 'SC7') Local nAtual := 0 Local aStrutSB1 := SB1->(DbStruct()) Local aStrutSD1 := SD1->(DbStruct()) Local aStrutSC7 := SC7->(DbStruct()) //Criando a View oView := FWFormView():New() oView:SetModel(oModel) //Adicionando os campos do cabeçalho oView:AddField('VIEW_SBM', oStPai, 'SBM_MASTER') //Grids dos filhos oView:AddGrid('VIEW_FILHO1', oStFilho1, 'SB1_FILHO1') oView:AddGrid('VIEW_FILHO2', oStFilho2, 'SB1_FILHO2') //Grid dos netos oView:AddGrid('VIEW_NETO1A', oStNeto1a, 'SD1_NETO1A') oView:AddGrid('VIEW_NETO1B', oStNeto1b, 'SC7_NETO1B') oView:AddGrid('VIEW_NETO2A', oStNeto2a, 'SD1_NETO2A') oView:AddGrid('VIEW_NETO2B', oStNeto2b, 'SC7_NETO2B') //Setando o dimensionamento de tamanho oView:CreateHorizontalBox('SUPERIOR', 30) oView:CreateHorizontalBox('INFERIOR', 70) //Criando a folder dos produtos (filhos) oView:CreateFolder('PASTA_FILHOS', 'INFERIOR') oView:AddSheet('PASTA_FILHOS', 'ABA_FILHO01', "Armazém 00") oView:AddSheet('PASTA_FILHOS', 'ABA_FILHO02', "Armazém 01") //Cria as caixas onde serão mostrados os dados dos filhos oView:CreateHorizontalBox('ITENS_FILHO01', 050,,, 'PASTA_FILHOS', 'ABA_FILHO01' ) oView:CreateHorizontalBox('ITENS_FILHO02', 050,,, 'PASTA_FILHOS', 'ABA_FILHO02' ) //Criando a folder dos pedidos (netos do Filho 1) oView:CreateHorizontalBox('NETOS_FILHO01', 050,,, 'PASTA_FILHOS', 'ABA_FILHO01' ) oView:CreateFolder('PASTA_NETO1', 'NETOS_FILHO01') oView:AddSheet('PASTA_NETO1', 'ABA_NETO1A', "Entradas") oView:AddSheet('PASTA_NETO1', 'ABA_NETO1B', "Compras") //Cria as caixas onde serão mostrados os dados dos netos do Filho 1 oView:CreateHorizontalBox('ITENS_NETO1A', 100,,, 'PASTA_NETO1', 'ABA_NETO1A' ) oView:CreateHorizontalBox('ITENS_NETO1B', 100,,, 'PASTA_NETO1', 'ABA_NETO1B' ) //Criando a folder dos pedidos (netos do Filho 2) oView:CreateHorizontalBox('NETOS_FILHO02', 050,,, 'PASTA_FILHOS', 'ABA_FILHO02' ) oView:CreateFolder('PASTA_NETO2', 'NETOS_FILHO02') oView:AddSheet('PASTA_NETO2', 'ABA_NETO2A', "Entradas") oView:AddSheet('PASTA_NETO2', 'ABA_NETO2B', "Compras") //Cria as caixas onde serão mostrados os dados dos netos do Filho 2 oView:CreateHorizontalBox('ITENS_NETO2A', 100,,, 'PASTA_NETO2', 'ABA_NETO2A' ) oView:CreateHorizontalBox('ITENS_NETO2B', 100,,, 'PASTA_NETO2', 'ABA_NETO2B' ) //Amarrando a view com as box oView:SetOwnerView('VIEW_SBM', 'SUPERIOR') oView:SetOwnerView('VIEW_FILHO1', 'ITENS_FILHO01') oView:SetOwnerView('VIEW_FILHO2', 'ITENS_FILHO02') oView:SetOwnerView('VIEW_NETO1A', 'ITENS_NETO1A') oView:SetOwnerView('VIEW_NETO1B', 'ITENS_NETO1B') oView:SetOwnerView('VIEW_NETO2A', 'ITENS_NETO2A') oView:SetOwnerView('VIEW_NETO2B', 'ITENS_NETO2B') //Retira campos da SB1 For nAtual := 1 To Len(aStrutSB1) If ! Alltrim(aStrutSB1[nAtual][01]) $ "B1_COD;B1_DESC;" oStFilho1:RemoveField(aStrutSB1[nAtual][01]) oStFilho2:RemoveField(aStrutSB1[nAtual][01]) EndIf Next //Retira campos da SD1 For nAtual := 1 To Len(aStrutSD1) If ! Alltrim(aStrutSD1[nAtual][01]) $ "D1_FILIAL;D1_DOC;D1_ITEM;D1_QUANT;D1_VUNIT;D1_TOTAL;D1_TES;D1_FORNECE;" oStNeto1a:RemoveField(aStrutSD1[nAtual][01]) oStNeto2a:RemoveField(aStrutSD1[nAtual][01]) EndIf Next //Retira campos da SC7 For nAtual := 1 To Len(aStrutSC7) If ! Alltrim(aStrutSC7[nAtual][01]) $ "C7_FILIAL;C7_NUM;C7_ITEM;C7_QUANT;C7_PRECO;C7_TOTAL;C7_TES;C7_FORNECE;" oStNeto1b:RemoveField(aStrutSC7[nAtual][01]) oStNeto2b:RemoveField(aStrutSC7[nAtual][01]) EndIf Next Return oView
Bom pessoal, por hoje é só.
Um grande abraço e até a próxima.
No meu não está carregando o botão de vizualizar
Bom dia Felipe, tudo bem?
Por acaso o fonte ou a user function tem apenas 7 caracteres?
Qualquer coisa, nos envie o fonte via grupo no Discord.
Abraços.
Arrebentou nesse vídeo hein! Muito bom!
Opa, obrigado pelo comentário jovem.
Grande abraço.
Opa eu aqui de novo , Legal seus posts sempre dando um help aqui . so uma duvido estas abas tazem uma grid ate consegui trazer minha SZX mas tem como trazer ela sem ser Grip e sim como cabecalho de cadastro como na Principal ?
Bom dia.
Sim, ao invés de usar AddGrid, você deve usar AddFields.
Abraços.
Obrigado pelos seus videos, são de muita valia! Ajudam demais.
Pode me tirar uma duvida, por favor? Vi que voce so colocou a opção de visualizar, porém, em meu caso, preciso incluir e alterar tambem e ao tentar salvar a inclusão ou alteração, ele da errorlog e percebi que é por causa desse relacionamento entre um campo e um valor:
oView:AddSheet(‘PASTA_FILHOS’, ‘ABA_FILHO01’, “Armazém 00”)
oView:AddSheet(‘PASTA_FILHOS’, ‘ABA_FILHO02’, “Armazém 01”)
Existe alguma forma de contornar esse problema?
Obrigado
Mencionei a parte errada do fonte:
//Criando os relacionamentos dos pais e filhos
aAdd(aRelFilho1, {‘B1_FILIAL’, ‘BM_FILIAL’})
aAdd(aRelFilho1, {‘B1_GRUPO’, ‘BM_GRUPO’})
aAdd(aRelFilho1, {‘B1_LOCPAD’, ’00’})
aAdd(aRelFilho2, {‘B1_FILIAL’, ‘BM_FILIAL’})
aAdd(aRelFilho2, {‘B1_GRUPO’, ‘BM_GRUPO’})
aAdd(aRelFilho2, {‘B1_LOCPAD’, ’01’})
//Criando o relacionamento do Filho 1
oModel:SetRelation(‘SB1_FILHO1’, aRelFilho1, SB1->(IndexKey(1)))
oModel:GetModel(‘SB1_FILHO1’):SetUniqueLine({“B1_FILIAL”,”B1_COD”})
//Criando o relacionamento do Filho 2
oModel:SetRelation(‘SB1_FILHO2’, aRelFilho2, SB1->(IndexKey(1)))
oModel:GetModel(‘SB1_FILHO2’):SetUniqueLine({“B1_FILIAL”,”B1_COD”})
Boa noite Márcio, obrigado pelo feedback jovem.
Então, como nesse caso, ele usa a mesma tabela em vários lugares diferentes, pode ser que dê problema mesmo.
O ideal seria você interceptar e fazer seu Commit de operação.
O único problema é que você teria que fazer manualmente os Reclocks.
Agora se forem tabelas diferentes em cada aba ou cada cenário, ai acho que o padrão atenderia.
Grande abraço.
Boa tarde, vi seu artigo muito bom, uma duvida, como faço para poder alterar somente a grid dos netos
Bom dia Alexandre, tudo bem? Obrigado pelo feedback.
Não sei se entendi muito bem a pergunta, mas você quer deixar a grid do filho e o pai, ambos sem alteração? Liberar apenas a parte do neto?
Se sim, você pode tentar usar o método SetOnlyView, deixando o pai e o filho como .T. e o neto sem precisar alterar, dentro da sua ModelDef, exemplo:
oModel:GetModel(“ZD2MASTER”):SetOnlyView(.T.)
Caso você seja um assinante premium, nos chame no WhatsApp, tem um exemplo que irá ao ar no dia 03/04/2023, ai te mandamos o fonte para você dar uma olhada.
Abraços.