 VB.NET - Controle de visitas 
médicas - II
  
VB.NET - Controle de visitas 
médicas - II
Este artigo é continuação do VB.NET - Controle de visitas médicas - I , se você não leu o artigo anterior clique no link e acompanhe a definição das tabelas da base de dados e do dataset tipado.
Nota: Para saber mais sobre datasets tipados veja os artigos:
Nossa aplicação tem por objetivo registrar as visitas a pacientes e gerar uma receita para cada paciente com os dados cadastrados para pacientes , medicamentos e diagnósticos. A aplicação deverá efetuar portanto o cadastro de pacientes , medicamentos e diagnósticos para em seguida registrar as visitas feitas usando os dados cadastrados.
Vamos criar o formulário de menu da aplicação incluindo um novo formulário no projeto com o nome de Menu.vb e definindo a sua propriedade isMdiContainer como True. A seguir inclua um componente no MenuStrip no formulário e crie um menu com as seguintes opções:
|  |  | 
Vamos agora incluir um novo formulário com o nome de pacientes.vb. Neste formulário será efetuado o cadastro dos pacientes. Vamos usar o assistente do VB 2005. Abra a janela Data Sources e selecione a tabela pacientes clicando a seguir na seta para baixo. Selecione a opção Details e a seguir arraste e solte a tabela no formulário criado. O assistente irá criar os campos da tabela e todo o menu para navegação e realização das operações CRUD (create, read, update e delete) no formulário. Veja na figura abaixo:
|  | 
Devemos incluir mais dois formulários: medicamentos.vb e diagnosticos.vb e repetir a operação feita acima usando as tabelas medicamentos e diagnosticos de forma a criar os formulários conforme abaixo:
|  |  | 
O formulário de visitas é o mais complexo pois nele devemos ter as informações cadastradas para além de atualizar as tabelas de visitas, pacienteMedicamentos e pacienteDiagnosticos também gerar o receituário para o paciente com gravação do arquivo com nome do paciente e impressão do mesmo.
Abaixo temos o leiaute do formulário contendo os controles relativos aos dados que deverão ser exibidos ou informados.
|  | 
Inclua um novo formulário visitas.vb no seu projeto. Menu Project opção Add Windows Form...
|  | Para poder exibir os pacientes 
    cadastrados vamos usar um controle combobox para fazer isto na janela 
    Data Sources selecione a tabela pacientes e selecione a opção Combobox 
    arrastando em seguida a tabela para o formulário visitas.vb. Serão criados os componentes no formulário: 
 Selecione o componente visual PacientesBindingNavigator e o exclua do projeto. Se você espiar o evento Load do formulário irá ver que o assistente criou a seguinte linha de código: Me.PacientesTableAdapter.Fill(Me.DiagnosticoDataSet.pacientes) Esta linha de código irá preencher a combobox 
    com os dados dos pacientes cadastrados que é exatamente o que queremos 
    obter. A combobox é identificada por pacientesComboBox. | 
Vamos repetir o processo acima para criar a combobox que irá exibir os diagnósticos cadastrados: diagnosticosComboBox (usando a tabela diagnosticos) e para a combobox que irá exibir os medicamentos cadastrados: MedicamentosCombobox (usando a tabela medicamentos). Clique na tabela na janela Data Sources selecione a opção ComboBox, arraste a tabela para o formulário e exclua o componente BindingNavigator.
Com isto já podemos selecionar o paciente e o diagnóstico para o paciente, mas aqui temos um problema, pois podemos ter mais de um medicamento indicado para o paciente/diagnóstico em questão. Para resolver isto vamos incluir um controle ListBox(lstbMedicamentos) e um botão de comando para que possamos selecionar um medicamento e clicando no botão de comando incluir o medicamento no ListBox com isto podermos indicar mais de um medicamento para o paciente/diagnóstico.
A solução adotada acima nos remete a um outro problema: devemos atualizar a tabela pacienteMedicamentos com o ID do medicamento mas temos somente o nome do mesmo na ListBox(lstbMedicamentos). Para poder obter o ID de cada medicamento incluído no controle ListBox temos que criar uma classe para obter esta informação. Inclua um módulo de classe no projeto; no menu Project selecione a opção Add Class e informe o nome lbMedicamentos.vb e no módulo inclua o seguinte código:
Nota: A ausência da propriedade ItemData presente no VB5/VB6 deverá ser criada usando a classe. Para saber mais sobre o assunto leia o artigo: VB.NET - Ressuscitando a propriedade ItemData
| Public Class lbMedicamentos
    Private sNome As String    Private iID As Integer
    ' construtor padrão vazioPublic Sub New() sNome = "" iID = 0 End Sub Public Sub New(ByVal Nome As String, ByVal ID As Integer) sNome = Nome iID = ID End Sub Public Property Nome() As String Get Return sNome End Get Set(ByVal sValue As String) sNome = sValue End Set End Property 
    'esta propriedade irá obter o ID do item do listboxPublic Property ItemData() As Int32 Get Return iID End Get Set(ByVal iValue As Int32) iID = iValue End Set End Property 
    Public Overrides Function ToString() As StringReturn sNome End Function End Class | 
Vamos voltar a falar sobre esta classe quando comentarmos o código da aplicação.
Inclua um controle TextBox (txtNotas) para informar as recomendações do médico ao paciente. Inclua também 3 botões de comando : btnSalvar , btnDescartar e btnSalvaImprime.
Nota: Devemos incluir arrastar e soltar as tabelas pacientesMedicamentos e pacienteDiagnosticos para o formulário para obtermos os componentes Adapter correspondentes.
Ao final desta etapa o formulário deverá exibir além dos controles incluídos os componentes no formulário conforme figura abaixo:
|  | 
Analisando o código da aplicação
Se você espiar o evento Load do formulário visitas.vb irá notar que o assistente já criou o código para preencher os TableAdapters criados.
| Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 'TODO: This line of code loads data into the 'DiagnosticoDataSet.visitas' table. You can move, or remove it, as needed. Me.VisitasTableAdapter.Fill(Me.DiagnosticoDataSet.visitas) 'TODO: This line of code loads data into the 'DiagnosticoDataSet.pacienteDiagnosticos' table. You can move, or remove it, as needed. Me.PacienteDiagnosticosTableAdapter.Fill(Me.DiagnosticoDataSet.pacienteDiagnosticos) 'TODO: This line of code loads data into the 'DiagnosticoDataSet.pacienteMedicamentos' table. You can move, or remove it, as needed. Me.PacienteMedicamentosTableAdapter.Fill(Me.DiagnosticoDataSet.pacienteMedicamentos) 'TODO: This line of code loads data into the 'DiagnosticoDataSet.medicamentos' table. You can move, or remove it, as needed. Me.MedicamentosTableAdapter.Fill(Me.DiagnosticoDataSet.medicamentos) 'TODO: This line of code loads data into the 'DiagnosticoDataSet.diagnosticos' table. You can move, or remove it, as needed. Me.DiagnosticosTableAdapter.Fill(Me.DiagnosticoDataSet.diagnosticos) 'TODO: This line of code loads data into the 'DiagnosticoDataSet.pacientes' table. You can move, or remove it, as needed. Me.PacientesTableAdapter.Fill(Me.DiagnosticoDataSet.pacientes) End Sub | 
O código do formulário principal que contém o menu de opções do sistema é o formulário menu.vb que irá abrir os demais formulários como formulários filhos do formulário MDI é dado a seguir:
| PublicClass Menu Private Sub PacientesToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PacientesToolStripMenuItem.Click My.Forms.pacientes.MdiParent = Me My.Forms.pacientes.Show() End Sub Private Sub MedicamentosToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MedicamentosToolStripMenuItem.Click My.Forms.medicamentos.MdiParent = Me My.Forms.medicamentos.Show() End Sub Private Sub DiagnósticosToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DiagnósticosToolStripMenuItem.Click My.Forms.diagnosticos.MdiParent = Me My.Forms.diagnosticos.Show() End Sub Private Sub RegistrarVisitaToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RegistrarVisitaToolStripMenuItem.Click My.Forms.visitas.MdiParent = Me My.Forms.visitas.Show() End Sub Private Sub SobreToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SobreToolStripMenuItem.Click My.Forms.sobre.MdiParent = Me My.Forms.sobre.Show() End Sub Private Sub SairToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SairToolStripMenuItem.Click If (MsgBox("Confirma encerramento da aplicação ? ", MsgBoxStyle.YesNo) = MsgBoxResult.Yes) Then Me.Close() End If End Sub EndClass | 
Vamos criar o código do evento Click do botão - Receitar Medicamento - ele deverá obter o medicamento selecionado no combobox e incluir no ListBox. Inclua o código abaixo no evento Click do botão:
| Private
    Sub 
    btnIncluiMedicamento_Click(ByVal 
    sender As System.Object,
    ByVal e 
    As System.EventArgs)
    Handles 
    btnIncluiMedicamento.Click'obtem o 
    ID e o nome do medicamento e usando a classe lbMedicamanto inclui no 
    controle ListBox Dim medicamentoID As Integer = Convert.ToInt32(MedicamentosComboBox.SelectedValue) Dim medicamentoNome As String = CType((MedicamentosComboBox.SelectedItem), System.Data.DataRowView).Row.ItemArray(1).ToString lstbMedicamentos.Items.Add(New lbMedicamentos(medicamentoNome, medicamentoID)) End Sub | 
As duas primeiras linhas de código obtêm o ID e o nome do medicamento a partir do combobox. Agora perceba a última linha de código; nela estamos incluindo o item selecionado na ListBox(lstbMedicamentos) usando a classe lbMedicamentos que foi criada para permitir a recuperação do ID do medicamento da ListBox, simulando a propriedade ItemData.
Vejamos a seguir o código do evento Click do botão - Gravar Registro e gera receituário:
| PrivateSub btnSalvar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSalvar.Click 'obtem o ID e o nome do paciente Dim pacienteID As Integer = Convert.ToInt32(PacientesComboBox.SelectedValue) pacienteNome =CType((PacientesComboBox.SelectedItem), System.Data.DataRowView).Row.ItemArray(1).ToString 'obtem o ID e a descrição do diagnóstico Dim diagnosticoID As Integer = Convert.ToInt32(DiagnosticosComboBox.SelectedValue) Dim diagnosticoDescricao As String = CType((DiagnosticosComboBox.SelectedItem), System.Data.DataRowView).Row.ItemArray(1).ToString 'define a data/hora como sendo a atual Dim datainicio As DateTime = DateTime.Now 'atualiza as tabelas de visitas e de PacientesDiagnosticos Me.VisitasTableAdapter.Insert(pacienteID, datainicio, txtNotas.Text) Me.PacienteDiagnosticosTableAdapter.Insert(pacienteID, diagnosticoID) Dim listaMedicamentos As lbMedicamentos Dim medicamentos As String = "" 'percorre o ListBox com os medicamentos receitados e inclui na receita For i As Integer = 0 To Me.lstbMedicamentos.Items.Count - 1 'selecione o item Me.lstbMedicamentos.SetSelected(i, True) ' Obtem o item selecionado listaMedicamentos = lstbMedicamentos.Items(lstbMedicamentos.SelectedIndex) 'inclui o item na tabela PacienteMedicamentos Dim nIncluido As Integer = PacienteMedicamentosTableAdapter.Insert(pacienteID, listaMedicamentos.ItemData, datainicio) medicamentos = medicamentos & (lstbMedicamentos.SelectedItem).ToString & vbCrLf 
 MessageBox.Show("Não foi possivel receitar o medicamento", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error) End If Next End Sub | 
Este código obtém os dados informados e usando o método Insert do objeto TableAdapter atualiza as tabelas pertinentes. Note que como recuperamos o ID do medicamento usando a propriedade ItemData da classe lbMedicamentos.
Criando o arquivo .doc para mesclar os dados da aplicação
Mas o código não esta completo devemos poder mesclar as informações com o documento Word para gerar a receita para o paciente com seu diagnóstico , medicamento e recomendações.
Vamos criar no Word , eu estou usando o Word 2003, um documento chamado receita.doc contendo as seguintes informações:
|  | 
Salve o arquivo em um diretório separado, eu usei a pasta d:\teste\. Neste documento as variáveis estão sendo identificadas pelo símbolo @ no início das mesmas pois iremos substituir cada uma delas com informações vindas da aplicação VB.
Agora podemos concluir o código do botão - Gravar Registro e gera receituário:
| PrivateSub btnSalvar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSalvar.Click 'obtem o ID e o nome do paciente Dim pacienteID As Integer = Convert.ToInt32(PacientesComboBox.SelectedValue) pacienteNome =CType((PacientesComboBox.SelectedItem), System.Data.DataRowView).Row.ItemArray(1).ToString 'obtem o ID e a descrição do diagnóstico Dim diagnosticoID As Integer = Convert.ToInt32(DiagnosticosComboBox.SelectedValue) Dim diagnosticoDescricao As String = CType((DiagnosticosComboBox.SelectedItem), System.Data.DataRowView).Row.ItemArray(1).ToString 'define a data/hora como sendo a atual Dim datainicio As DateTime = DateTime.Now 'atualiza as tabelas de visitas e de PacientesDiagnosticos Me.VisitasTableAdapter.Insert(pacienteID, datainicio, txtNotas.Text) Me.PacienteDiagnosticosTableAdapter.Insert(pacienteID, diagnosticoID) Dim listaMedicamentos As lbMedicamentos Dim medicamentos As String = "" 'percorre o ListBox com os medicamentos receitados e inclui na receita For i As Integer = 0 To Me.lstbMedicamentos.Items.Count - 1 'selecione o item Me.lstbMedicamentos.SetSelected(i, True) ' Obtem o item selecionado listaMedicamentos = lstbMedicamentos.Items(lstbMedicamentos.SelectedIndex) 'inclui o item na tabela PacienteMedicamentos Dim nIncluido As Integer = PacienteMedicamentosTableAdapter.Insert(pacienteID, listaMedicamentos.ItemData, datainicio) medicamentos = medicamentos & (lstbMedicamentos.SelectedItem).ToString & vbCrLf 
 MessageBox.Show("Não foi possivel receitar o medicamento", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error) End If Next 'inicia geração da receita com substituição dos valores Try 'Instancia a Aplicação Word. objWord = CreateObject("Word.Application") 'Abre o documento aviso.doc do Microsoft Word. objWord.Documents.Open("d:\teste\receita.doc") 'Procura pela palavra "@escola" e substitui pelo conteúdo indicado SubstituiVariavel("@clinica", "JcmSoft - Clinica Geral") SubstituiVariavel("@medico", "Dr. José Carlos Macoratti") SubstituiVariavel("@data", Today) SubstituiVariavel("@endereco", "SHS 912 Conjunto C Bloco A Sala 21") SubstituiVariavel("@cidade", "Brasilia-DF") SubstituiVariavel("@paciente", pacienteNome) SubstituiVariavel("@diagnostico", diagnosticoDescricao) SubstituiVariavel("@medicamentos", medicamentos) If txtNotas.Text.Length > 0 Then SubstituiVariavel("@recomendacao", txtNotas.Text) End If SubstituiVariavel("@clinico", "Dr. Jose C. Macoratti") 
 'torna o Word visivel objWord.visible =True 'habilita o botão para fechar o word sem salvar Else fechaWord()End If Catch ex As Exception MsgBox("Ocorreu um erro durante a geração do receituário", MsgBoxStyle.Critical, "Erro") objWord.ActiveDocument.Close(False) objWord.Quit() objWord =Nothing MsgBox(ex.Message)End Try 
     | 
Para podermos usar este código temos que efetuar uma referência COM no nosso projeto. Existem outras formam de efetuar uma chamada a uma aplicativo Office a partir do VB.NET. Para referenciar o Word no seu projeto clique com o botão direito do mouse sobre o nome do projeto selecione a opção Add Reference. A seguir clique na guia COM da janela Add Reference e selecione a opção : Microsoft Word 11.0 Object Library (pode haver variações dependendo da sua versão do Word).
|  | 
A seguir temos o código da rotina SubstituiVariavel que irá mesclar as informações da aplicação VB com o arquivo .doc.
| Private Sub SubstituiVariavel(ByVal Achar As String, ByVal Substituir As String)
        'procura a variável e substitui o valor With objWord.Selection.Find .Text = Achar.ToString .Replacement.Text = Substituir.ToString .Forward = True .Format = False .MatchCase = False .MatchWholeWord = False .MatchWildcards = False .MatchSoundsLike = False             .MatchAllWordForms = False
            While .Execute = TrueobjWord.Selection.Select() System.Windows.Forms.Clipboard.SetDataObject(Substituir) objWord.Selection.Paste() End While End With End Sub 
 | 
A seguir o código dos demais botões de comando:
| Private Sub btnSalvaImprime_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSalvaImprime.Click fechaWord(pacienteNome) End Sub Private Sub btnDescartar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDescartar.Click Me.Close() End Sub | 
A rotina fechaWord irá salvar e imprimir o documento Word usando o nome do paciente com a extensão doc no caminho definido. Perceba que o parâmetro pacienteNome é opcional e por isto tem que ter um valor padrão definido. Se o nome for passado o arquivo é salvo e impresso e somente depois será fechado.
| Private Sub fechaWord(Optional ByVal pacienteNome As String = "")
        'se o nome do paciente foi usado como parâmetro salva o arquivo e imprimeIf pacienteNome.Length > 0 Then             objWord.ActiveDocument.SaveAs(FileName:=caminho & pacienteNome & ".doc", LockComments:=False, Password:="", AddToRecentFiles:=True, 
                     WritePassword:="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, SaveNativePictureFormat:=False, SaveFormsData:=False, 
                     SaveAsAOCELetter:=False)
objWord.Application.PrintOut(FileName:="", Copies:=1, Pages:="", ManualDuplexPrint:=False, Collate:=True, Background:=True, PrintToFile:= _ False, PrintZoomColumn:=0, PrintZoomRow:=0, PrintZoomPaperWidth:=0, _ PrintZoomPaperHeight:=0) End If 'Fecha o documento Word objWord.ActiveDocument.Close(False) 'Fecha o Word objWord.Quit() objWord = Nothing End Sub 
 | 
Inclua no início do código do formulário as seguintes declarações para o objeto Word , para o caminho do arquivo .doc a ser salvo e para o nome do paciente.
Dim
objWord As ObjectJá podemos rodar a aplicação e ver o resultado conforme exibido nas figuras a seguir:
1- O formulário visitas.vb preenchido com os dados já cadastrados:
|  | 
2- Ao clicar no botão - Gravar Registro e gerar receituário, as informações são mescladas com o arquivo receita.doc , o arquivo é salvo e impresso na impressora padrão. Abaixo o arquivo .doc exibindo as informações após efetuar a substituição das variáveis.
|  | 
Como eu já mencionei existem maneiras mais elegantes para usar os aplicativos Office do que apelar para o COM , em futuros artigos estarei abordando estas possibilidades. De qualquer forma, como você acompanhou é bem simples criar o seu aplicativo no VB 2005 e fazer a integração com o Word.
O texto do arquivo receita.doc é meramente ilustrativo e você pode fazer os ajustes necessários as suas necessidades bem como usar o seu talento para aperfeiçoar o projeto expandido-o com novas funcionalidades.
Nota: Se você analisar com cuidado a normalização utilizada irá verificar que alguns ajustes serão necessários dependendo do ajuste que você pretende fazer na aplicação.
O projeto completo esta no Super DVD .NET (com opção de relatórios via printDocument)
Até o próximo artigo  ... 
José Carlos Macoratti