Fazendo Arquivos EDI com C# aplicando POO Parte 1
Esta série de quatro artigos são republicações da série “Fazendo Arquivos EDI com C# aplicando POO” que coloquei, a algum tempo atrás, em meu site do Multiply.
Este é um artigo que propõe a construção de um lay-out de arquivo do tipo fixo-blocado, utilizando a linguagem C# e com técnicas de Programação Orientada a Objetos.
Um arquivo do tipo fixo-blocado é utilizado por várias empresas com a finalidade de trocar informações entre sistemas (daí o EDI - Electronic Data Interchange do título) através de troca de arquivos.
Sua característica principal é que os campos em cada um dos registros (linhas do arquivo) possuirem tamanho fixo (em quantidade de caracteres) e são organizados sequencialmente.
Um arquivo é composto de várias linhas, e cada linha de vários campos descritos acima; cada campo possui uma máscara, ou formatação.
Cada sistema que utiliza-se deste método possui um documento onde são descritas as características do arquivo, tais como o tamanho dos registros, tipos de registros e a formatação dos campos, o famigerado lay-out.
Geralmente, cada arquivo possui um registro Header (Cabeçalho), onde geralmente é apresentado campos que indicam a data de geração, tipo de arquivo, entre outros;
vários registros detalhe e um registro final (Trailler).
Para o artigo, vamos construir um lay-out bem simples, e um programa para apresentar os registros em tela, com os campos devidamente separados.
O lay-out proposto consiste em:
Descrição Tipo Tamanho Posição Inicial Obs. Nome X 40 1 Data de Nascimento D 8 41 DDMMAAAA Tipo de Pessoa X 1 49 F ou J Documento N(0) 20 50 Saldo Atual N(2) 12 70 10 posições, 2 decimais s/ separador
Primeiramente, vamos "transformar" o conceito de arquivo fixo blocado em objetos, ou seja, modelar as classes que irão compor o nosso projeto.
Bem, você poderia perguntar, "simplesmente posso construir um programa que separa substrings, aplica em cada campo e exibe na tela, não é"?
Sim, isso pode ser feito, eu também já fiz várias vezes dessa forma, sempre repetindo o mesmo código várias vezes, claro que com as devidas sutilezas em cada implementação.
Minha proposta neste artigo é a construção de um "motor", que tem a capacidade de interpretar qualquer tipo de layout, um mecanismo básico, que poderá ser implementado
em qualquer layout específico.
Retomando o raciocínio... Um arquivo do tipo fixo-blocado é uma *coleção* de registros; cada registro é uma *coleção* de campos, e estes campos possuem atributos tais como o seu tamanho de caracteres, o seu tipo (que pode ser alfanumérico, data, numérico, etc), uma máscara (por exemplo, DDMMAAAA - data sem separador), quantidade de casas decimais, no caso de numéricos e sua posição inicial dentro da linha.
Vejam o abuso da palavra *coleção*. Significa que utilizaremos bastante coleções em nosso projeto.
Vamos começar pela parte mais básica (e a mais complexa, por sinal) de um arquivo: os campos de cada registro. Cada campo possui os atributos conforme dito acima. Temos os seguintes atributos em cada campo:
- Tipo
- Descrição
- Tamanho
- Posições Inicial e Final
- Quantidade Casas Decimais
Podemos ainda ter:
- Valor Padrão
- Separadores de data, decimais, milhar, hora, etc.
- Ordem do campo no Registro.
Os tipos de campo, podem ser basicamente numéricos e alfanuméricos, sendo os outros derivados deste, com as suas respectivas máscaras de formatação, podendo formar datas separadas por barra, ponto, números decimais sem separador, entre muitos outros. Para delimitar os tipos com que a nossa classe de campo irá trabalhar, vamos representar cada tipo através de um item de uma enumeração, assim podemos saber quais tipos poderemos ter em cada campo. Veja a implementação a seguir:
1: /// <summary>
2: /// Representa cada tipo de dado possível em um arquivo EDI.
3: /// </summary>
4: public enum TTiposDadoEDI
5: {
6: /// <summary>
7: /// Representa um campo alfanumérico, alinhado à esquerda e com brancos à direita. A propriedade ValorNatural é do tipo String
8: /// </summary>
9: ediAlpha,
10: /// <summary>
11: /// Representa um campo numérico inteiro alinhado à direita com zeros à esquerda. A propriedade ValorNatural é do tipo Int ou derivados
12: /// </summary>
13: ediInteiro,
14: /// <summary>
15: /// Representa um campo numérico com decimais, sem o separador de decimal. A propriedade ValorNatural é do tipo Double
16: /// </summary>
17: ediNumericoSemSeparador,
18: /// <summary>
19: /// Representa um campo numérico com decimais, com o caracter ponto (.) como separador decimal,
20: /// alinhado à direita com zeros à esquerda. A propriedade ValorNatural é do tipo Double
21: /// </summary>
22: ediNumericoComPonto,
23: /// <summary>
24: /// Representa um campo numérico com decimais, com o caracter vírgula (,) como separador decimal,
25: /// alinhado à direita com zeros à esquerda. A propriedade ValorNatural é do tipo Double
26: /// </summary>
27: ediNumericoComVirgula,
28: /// <summary>
29: /// Representa um campo de data no formato ddm/mm/aaaa. A propriedade ValorNatural é do tipo DateTime
30: /// </summary>
31: ediDataDDMMAAAA,
32: /// <summary>
33: /// Representa um campo de data no formato aaaa/mm/dd. A propriedade ValorNatural é do tipo DateTime
34: /// </summary>
35: ediDataAAAAMMDD,
36: /// <summary>
37: /// Representa um campo de data no formato dd/mm. A propriedade ValorNatural é do tipo DateTime, com o ano igual a 1900
38: /// </summary>
39: ediDataDDMM,
40: /// <summary>
41: /// Representa um campo de data no formato mm/aaaa. A propriedade ValorNatural é do tipo DateTime, com o dia igual a 01
42: /// </summary>
43: ediDataMMAAAA,
44: /// <summary>
45: /// Representa um campo de data no formato mm/dd. A propriedade ValorNatural é do tipo DateTime com o ano igual a 1900
46: /// </summary>
47: ediDataMMDD,
48: /// <summary>
49: /// Representa um campo de hora no formato HH:MM. A propriedade ValorNatural é do tipo DateTime, com a data igual a 01/01/1900
50: /// </summary>
51: ediHoraHHMM,
52: /// <summary>
53: /// Representa um campo de hora no formato HH:MM:SS. A propriedade ValorNatural é do tipo DateTime, com a data igual a 01/01/1900
54: /// </summary>
55: ediHoraHHMMSS,
56: /// <summary>
57: /// Representa um campo de data no formato DD/MM/AAAA. A propriedade ValorNatural é do tipo DateTime.
58: /// </summary>
59: ediDataDDMMAA,
60: /// <summary>
61: /// Representa um campo de data no formato DD/MM/AAAA, porém colocando zeros no lugar de espaços no ValorFormatado. A propriedade
62: /// ValorNatural é do tipo DateTime, e este deve ser nulo caso queira que a data seja zero.
63: /// </summary>
64: ediDataDDMMAAAAWithZeros,
65: /// <summary>
66: /// Representa um campo de data no formato AAAA/MM/DD, porém colocando zeros no lugar de espaços no ValorFormatado. A propriedade
67: /// ValorNatural é do tipo DateTime, e este deve ser nulo caso queira que a data seja zero.
68: /// </summary>
69: ediDataAAAAMMDDWithZeros
70: }
Cada tipo suportado está comentado, dispensando maiores comentários a respeito deles.
Ah, quanto ao prefixo "T" em cada classe... coisas de quem veio do Delphi :-)
Agora, vamos implementar a classe básica de interpretação dos layouts, em partes:
1: public class TCampoRegistroEDI
2: {
3: #region Variáveis Privadas
4: private string _DescricaoCampo;
5: private TTiposDadoEDI _TipoCampo;
6: private int _TamanhoCampo;
7: private int _QtdDecimais;
8: private object _ValorNatural;
9: private string _ValorFormatado;
10: private int _OrdemNoRegistroEDI;
11: private string _SeparadorDatas;
12: private string _SeparadorHora;
13: private int _PosicaoInicial;
14: private int _PosicaoFinal;
15: #endregion
16:
17: #region Propriedades
18: /// <summary>
19: /// Descrição do campo no registro EDI (meramente descritivo)
20: /// </summary>
21: public string DescricaoCampo
22: {
23: get { return _DescricaoCampo; }
24: set { _DescricaoCampo = value; }
25: }
26:
27: /// <summary>
28: /// Tipo de dado de ORIGEM das informações do campo EDI.
29: /// </summary>
30: public TTiposDadoEDI TipoCampo
31: {
32: get { return _TipoCampo; }
33: set { _TipoCampo = value; }
34: }
35:
36: /// <summary>
37: /// Tamanho em caracteres do campo no arquivo EDI (DESTINO)
38: /// </summary>
39: public int TamanhoCampo
40: {
41: get { return _TamanhoCampo; }
42: set { _TamanhoCampo = value; }
43: }
44:
45: /// <summary>
46: /// Quantidade de casas decimais do campo, caso ele seja do tipo numérico sem decimais. Caso
47: /// não se aplique ao tipo de dado, o valor da propriedade será ignorado nas funções de formatação.
48: /// </summary>
49: public int QtdDecimais
50: {
51: get { return _QtdDecimais; }
52: set { _QtdDecimais = value; }
53: }
54:
55: /// <summary>
56: /// Valor de ORIGEM do campo, sem formatação, no tipo de dado adequado ao campo. O valor deve ser atribuido
57: /// com o tipo de dado adequado ao seu proposto, por exemplo, Double para representar valor, DateTime para
58: /// representar datas e/ou horas, etc.
59: /// </summary>
60: public object ValorNatural
61: {
62: get { return _ValorNatural; }
63: set { _ValorNatural = value; }
64: }
65:
66: /// <summary>
67: /// Valor formatado do campo, pronto para ser utilizado no arquivo EDI. A formatação será de acordo
68: /// com a especificada na propriedade TipoCampo, com numéricos alinhados à direita e zeros à esquerda
69: /// e campos alfanuméricos alinhados à esquerda e com brancos à direita.
70: /// Também pode receber o valor vindo do arquivo EDI, para ser decodificado e o resultado da decodificação na propriedade
71: /// ValorNatural
72: /// </summary>
73: public string ValorFormatado
74: {
75: get { return _ValorFormatado; }
76: set { _ValorFormatado = value; }
77: }
78:
79: /// <summary>
80: /// Número de ordem do campo no registro EDI
81: /// </summary>
82: public int OrdemNoRegistroEDI
83: {
84: get { return _OrdemNoRegistroEDI; }
85: set { _OrdemNoRegistroEDI = value; }
86: }
87:
88: /// <summary>
89: /// Caractere separador dos elementos de campos com o tipo DATA. Colocar null caso esta propriedade
90: /// não se aplique ao tipo de dado.
91: /// </summary>
92: public string SeparadorDatas
93: {
94: get { return _SeparadorDatas; }
95: set { _SeparadorDatas = value; }
96: }
97:
98: /// <summary>
99: /// Caractere separador dos elementos de campos com o tipo HORA. Colocar null caso esta propriedade
100: /// não se aplique ao tipo de dado.
101: /// </summary>
102: public string SeparadorHora
103: {
104: get { return _SeparadorHora; }
105: set { _SeparadorHora = value; }
106: }
107:
108: /// <summary>
109: /// Posição do caracter inicial do campo no arquivo EDI
110: /// </summary>
111: public int PosicaoInicial
112: {
113: get { return _PosicaoInicial; }
114: set { _PosicaoInicial = value; }
115: }
116:
117: public int PosicaoFinal
118: {
119: get { return _PosicaoFinal; }
120: set { _PosicaoFinal = value; }
121: }
122: #endregion
Note que temos os atributos que abstraimos no início deste artigo, e dois atributos mais "curiosos":
- ValorNatural, do tipo object: Irá receber o valor do campo no tipo de dado que ele representa, ou seja, se for número inteiro, um int, se for decimal, double,
data, DateTime e assim por diante. Através do tipo de dados iremos aplicar a formatação adequada.
- ValorFormatado, do tipo string: Irá receber o valor já formatado, no momento da interpretação de um arquivo, e fornecerá o valor formatado no momento da geração.
Temos também os construtores da classe, que irão inicializar as propriedades com valores padrão:
1: #region Construtores
2: /// <summary>
3: /// Cria um objeto TCampoRegistroEDI
4: /// </summary>
5: public TCampoRegistroEDI()
6: { }
7:
8: /// <summary>
9: /// Cria um objeto do tipo TCampoRegistroEDI inicializando as propriedades básicas.
10: /// </summary>
11: /// <param name="pTipoCampo">Tipo de dado de origem dos dados</param>
12: /// <param name="pTamanho">Tamanho em caracteres do campo (destino)</param>
13: /// <param name="pDecimais">Quantidade de decimais do campo (destino)</param>
14: /// <param name="pValor">Valor do campo (Origem), no tipo de dado adequado ao propósito do campo</param>
15: /// <param name="pSeparadorHora">Separador de hora padrão; null para sem separador</param>
16: /// <param name="pSeparadorData">Separador de data padrão; null para sem separador</param>
17: /// <param name="pPosicaoInicial">Posição Inicial do Campo no Arquivo</param>
18: public TCampoRegistroEDI(TTiposDadoEDI pTipoCampo, int pTamanho, int pDecimais, object pValor, string pSeparadorHora, string pSeparadorData, int pPosicaoInicial)
19: {
20: this._TipoCampo = pTipoCampo;
21: this._TamanhoCampo = pTamanho;
22: this._QtdDecimais = pDecimais;
23: this._ValorNatural = pValor;
24: this._SeparadorHora = pSeparadorHora;
25: this._SeparadorDatas = pSeparadorData;
26: this._OrdemNoRegistroEDI = 0;
27: this._DescricaoCampo = "";
28: this._PosicaoInicial = pPosicaoInicial - 1; //Compensa a indexação com base em zero
29: this._PosicaoFinal = pPosicaoInicial + this._TamanhoCampo;
30: }
31: #endregion
Agora que vem a parte legal, que é onde será feita a formatação do valor informado através da propriedade ValorNatural em uma formatação condizente com o nosso lay-out:
No momento da geração do arquivo, vamos utilizar:
1: /// <summary>
2: /// Aplica formatação ao valor do campo em ValorNatural, colocando o resultado na propriedade ValorFormatado
3: /// </summary>
4: public void CodificarNaturalParaEDI()
5: {
6: switch (this._TipoCampo)
7: {
8: case TTiposDadoEDI.ediAlpha:
9: {
10: this._ValorFormatado = this._ValorNatural.ToString().Trim().PadRight(this._TamanhoCampo, ' ');
11: break;
12: }
13: case TTiposDadoEDI.ediInteiro:
14: {
15: this._ValorFormatado = this._ValorNatural.ToString().Trim().PadLeft(this._TamanhoCampo, '0');
16: break;
17: }
18: case TTiposDadoEDI.ediNumericoSemSeparador:
19: {
20: string Formatacao = "{0:f" + this._QtdDecimais.ToString() + "}";
21: this._ValorFormatado = String.Format(Formatacao, this._ValorNatural).Replace(",","").Replace(".","").Trim().PadLeft(this._TamanhoCampo, '0');
22: break;
23: }
24: case TTiposDadoEDI.ediNumericoComPonto:
25: {
26: string Formatacao = "{0:f" + this._QtdDecimais.ToString() + "}";
27: this._ValorFormatado = String.Format(Formatacao, this._ValorNatural).Replace(",", ".").Trim().PadLeft(this._TamanhoCampo, '0');
28: break;
29: }
30: case TTiposDadoEDI.ediNumericoComVirgula:
31: {
32: string Formatacao = "{0:f" + this._QtdDecimais.ToString() + "}";
33: this._ValorFormatado = String.Format(Formatacao, this._ValorNatural).Replace(".", ",").Trim().PadLeft(this._TamanhoCampo, '0');
34: break;
35: }
36: case TTiposDadoEDI.ediDataAAAAMMDD:
37: {
38: if ( (DateTime)this._ValorNatural != DateTime.MinValue)
39: {
40: string sep = (this._SeparadorDatas == null ? "" : this._SeparadorDatas.ToString());
41: string Formatacao = "{0:yyyy" + sep + "MM" + sep + "dd}";
42: this._ValorFormatado = String.Format(Formatacao, this._ValorNatural);
43: }
44: else
45: {
46: this._ValorNatural = "";
47: goto case TTiposDadoEDI.ediAlpha;
48: }
49: break;
50: }
51: case TTiposDadoEDI.ediDataDDMM:
52: {
53: if ((DateTime)this._ValorNatural != DateTime.MinValue)
54: {
55: string sep = (this._SeparadorDatas == null ? "" : this._SeparadorDatas.ToString());
56: string Formatacao = "{0:dd" + sep + "MM}";
57: this._ValorFormatado = String.Format(Formatacao, this._ValorNatural);
58: }
59: else
60: {
61: this._ValorNatural = "";
62: goto case TTiposDadoEDI.ediAlpha;
63: }
64: break;
65: }
66: case TTiposDadoEDI.ediDataDDMMAAAA:
67: {
68: if ((DateTime)this._ValorNatural != DateTime.MinValue)
69: {
70: string sep = (this._SeparadorDatas == null ? "" : this._SeparadorDatas.ToString());
71: string Formatacao = "{0:dd" + sep + "MM" + sep + "yyyy}";
72: this._ValorFormatado = String.Format(Formatacao, this._ValorNatural);
73: }
74: else
75: {
76: this._ValorNatural = "";
77: goto case TTiposDadoEDI.ediAlpha;
78: }
79: break;
80: }
81: case TTiposDadoEDI.ediDataDDMMAA:
82: {
83: if ((DateTime)this._ValorNatural != DateTime.MinValue)
84: {
85: string sep = (this._SeparadorDatas == null ? "" : this._SeparadorDatas.ToString());
86: string Formatacao = "{0:dd" + sep + "MM" + sep + "yy}";
87: this._ValorFormatado = String.Format(Formatacao, this._ValorNatural);
88: }
89: else
90: {
91: this._ValorNatural = "";
92: goto case TTiposDadoEDI.ediAlpha;
93: }
94: break;
95: }
96: case TTiposDadoEDI.ediDataMMAAAA:
97: {
98: if ((DateTime)this._ValorNatural != DateTime.MinValue)
99: {
100: string sep = (this._SeparadorDatas == null ? "" : this._SeparadorDatas.ToString());
101: string Formatacao = "{0:MM" + sep + "yyyy}";
102: this._ValorFormatado = String.Format(Formatacao, this._ValorNatural);
103: }
104: else
105: {
106: this._ValorNatural = "";
107: goto case TTiposDadoEDI.ediAlpha;
108: }
109: break;
110: }
111: case TTiposDadoEDI.ediDataMMDD:
112: {
113: if ((DateTime)this._ValorNatural != DateTime.MinValue)
114: {
115: string sep = (this._SeparadorDatas == null ? "" : this._SeparadorDatas.ToString());
116: string Formatacao = "{0:MM" + sep + "dd}";
117: this._ValorFormatado = String.Format(Formatacao, this._ValorNatural);
118: }
119: else
120: {
121: this._ValorNatural = "";
122: goto case TTiposDadoEDI.ediAlpha;
123: }
124: break;
125: }
126: case TTiposDadoEDI.ediHoraHHMM:
127: {
128: string sep = (this._SeparadorHora == null ? "" : this._SeparadorHora.ToString());
129: string Formatacao = "{0:HH" + sep + "mm}";
130: this._ValorFormatado = String.Format(Formatacao, this._ValorNatural);
131: break;
132: }
133: case TTiposDadoEDI.ediHoraHHMMSS:
134: {
135: string sep = (this._SeparadorHora == null ? "" : this._SeparadorHora.ToString());
136: string Formatacao = "{0:HH" + sep + "mm" + sep + "ss}";
137: this._ValorFormatado = String.Format(Formatacao, this._ValorNatural);
138: break;
139: }
140: case TTiposDadoEDI.ediDataDDMMAAAAWithZeros:
141: {
142: string sep = (this._SeparadorDatas == null ? "" : this._SeparadorDatas.ToString());
143: if ( (this._ValorNatural != null) || (!this.ValorNatural.ToString().Trim().Equals("")))
144: {
145: string Formatacao = "{0:dd" + sep + "MM" + sep + "yyyy}";
146: this._ValorFormatado = String.Format(Formatacao, this._ValorNatural);
147: }
148: else
149: {
150: this._ValorFormatado = "00" + sep + "00" + sep + "0000";
151: }
152: break;
153: }
154: case TTiposDadoEDI.ediDataAAAAMMDDWithZeros:
155: {
156: string sep = (this._SeparadorDatas == null ? "" : this._SeparadorDatas.ToString());
157: if (this._ValorNatural != null)
158: {
159: string Formatacao = "{0:yyyy" + sep + "MM" + sep + "dd}";
160: this._ValorFormatado = String.Format(Formatacao, this._ValorNatural);
161: }
162: else
163: {
164: this._ValorFormatado = "00" + sep + "00" + sep + "0000";
165: }
166: break;
167: }
168: }
169: }
Note que nesta ocasião, dependendo do tipo de dado informado, fazemos a conversão do object em ValorNaturalpara string, aplicando a máscara informada na mesma, e retornando essa string na propriedade ValorFormatado
Já no momento da interpretação do campo, iremos utilizar o seguinte:
1: /// <summary>
2: /// Transforma o valor vindo do campo do registro EDI da propriedade ValorFormatado para o valor natural (com o tipo
3: /// de dado adequado) na propriedade ValorNatural
4: /// </summary>
5: public void DecodificarEDIParaNatural()
6: {
7: if (this._ValorFormatado.Trim().Equals(""))
8: {
9: this._ValorNatural = null;
10: }
11: else
12: {
13: switch (this._TipoCampo)
14: {
15: case TTiposDadoEDI.ediAlpha:
16: {
17: this._ValorNatural = this._ValorFormatado.ToString().Trim();
18: break;
19: }
20: case TTiposDadoEDI.ediInteiro:
21: {
22: this._ValorNatural = long.Parse(this._ValorFormatado.ToString().Trim());
23: break;
24: }
25: case TTiposDadoEDI.ediNumericoSemSeparador:
26: {
27: string s = this._ValorFormatado.Substring(0, this._ValorFormatado.Length - this._QtdDecimais) + "," + this._ValorFormatado.Substring(this._ValorFormatado.Length - this._QtdDecimais, this._QtdDecimais);
28: this._ValorNatural = Double.Parse(s.Trim());
29: break;
30: }
31: case TTiposDadoEDI.ediNumericoComPonto:
32: {
33: this._ValorNatural = Double.Parse(this._ValorFormatado.ToString().Replace(".", ",").Trim());
34: break;
35: }
36: case TTiposDadoEDI.ediNumericoComVirgula:
37: {
38: this._ValorNatural = Double.Parse(this._ValorFormatado.ToString().Trim().Replace(".", ","));
39: break;
40: }
41: case TTiposDadoEDI.ediDataAAAAMMDD:
42: {
43: if (!this._ValorFormatado.Trim().Equals(""))
44: {
45: string cAno = "";
46: string cMes = "";
47: string cDia = "";
48: if (this._SeparadorDatas != null)
49: {
50: string[] split = this._ValorFormatado.Split(this._SeparadorDatas.ToCharArray());
51: cAno = split[0];
52: cMes = split[1];
53: cDia = split[2];
54: }
55: else
56: {
57: cAno = this._ValorFormatado.Substring(0, 4);
58: cMes = this._ValorFormatado.Substring(4, 2);
59: cDia = this._ValorFormatado.Substring(6, 2);
60: }
61: if ((cDia.Equals("00") && cMes.Equals("00") && cAno.Equals("0000")))
62: {
63: this._ValorNatural = null;
64: }
65: else
66: {
67: this._ValorNatural = DateTime.Parse(cDia + "/" + cMes + "/" + cAno);
68: }
69: }
70: else
71: {
72: this._ValorNatural = null;
73: }
74: break;
75: }
76: case TTiposDadoEDI.ediDataDDMM:
77: {
78: if (!this._ValorFormatado.Trim().Equals(""))
79: {
80: string cAno = "1900";
81: string cMes = "";
82: string cDia = "";
83: if (this._SeparadorDatas != null)
84: {
85: string[] split = this._ValorFormatado.Split(this._SeparadorDatas.ToCharArray());
86: cMes = split[1];
87: cDia = split[0];
88: }
89: else
90: {
91: cMes = this._ValorFormatado.Substring(2, 2);
92: cDia = this._ValorFormatado.Substring(0, 2);
93: }
94: this._ValorNatural = DateTime.Parse(cDia + "/" + cMes + "/" + cAno);
95: }
96: else
97: {
98: this._ValorNatural = null;
99: }
100: break;
101: }
102: case TTiposDadoEDI.ediDataDDMMAAAA:
103: {
104: string cDia = "";
105: string cMes = "";
106: string cAno = "";
107: if (this._SeparadorDatas != null)
108: {
109: string[] split = this._ValorFormatado.Split(this._SeparadorDatas.ToCharArray());
110: cAno = split[2];
111: cMes = split[1];
112: cDia = split[0];
113: }
114: else
115: {
116: cDia = this._ValorFormatado.Substring(0, 2);
117: cMes = this._ValorFormatado.Substring(2, 2);
118: cAno = this._ValorFormatado.Substring(4, 4);
119: }
120: if ((cDia.Equals("00") && cMes.Equals("00") && cAno.Equals("0000")) || this._ValorFormatado.Trim().Equals(""))
121: {
122: this._ValorNatural = DateTime.Parse("01/01/1900"); //data start
123: }
124: else
125: {
126: this._ValorNatural = DateTime.Parse(cDia + "/" + cMes + "/" + cAno);
127: }
128: break;
129: }
130: case TTiposDadoEDI.ediDataDDMMAA:
131: {
132: string cDia = "";
133: string cMes = "";
134: string cAno = "";
135: if (this._SeparadorDatas != null)
136: {
137: string[] split = this._ValorFormatado.Split(this._SeparadorDatas.ToCharArray());
138: cAno = split[2];
139: cMes = split[1];
140: cDia = split[0];
141: }
142: else
143: {
144: cDia = this._ValorFormatado.Substring(0, 2);
145: cMes = this._ValorFormatado.Substring(2, 2);
146: cAno = this._ValorFormatado.Substring(4, 2);
147: }
148: this._ValorNatural = DateTime.Parse(cDia + "/" + cMes + "/" + cAno);
149: break;
150: }
151: case TTiposDadoEDI.ediDataMMAAAA:
152: {
153: string cDia = "01";
154: string cMes = "";
155: string cAno = "";
156: if (this._SeparadorDatas != null)
157: {
158: string[] split = this._ValorFormatado.Split(this._SeparadorDatas.ToCharArray());
159: cAno = split[1];
160: cMes = split[0];
161: }
162: else
163: {
164: cMes = this._ValorFormatado.Substring(0, 2);
165: cAno = this._ValorFormatado.Substring(2, 4);
166: }
167: this._ValorNatural = DateTime.Parse(cDia + "/" + cMes + "/" + cAno);
168: break;
169: }
170: case TTiposDadoEDI.ediDataMMDD:
171: {
172: string cDia = "";
173: string cMes = "";
174: string cAno = "1900";
175: if (this._SeparadorDatas != null)
176: {
177: string[] split = this._ValorFormatado.Split(this._SeparadorDatas.ToCharArray());
178: cMes = split[0];
179: cDia = split[1];
180: }
181: else
182: {
183: cDia = this._ValorFormatado.Substring(2, 2);
184: cMes = this._ValorFormatado.Substring(0, 2);
185: }
186: this._ValorNatural = DateTime.Parse(cDia + "/" + cMes + "/" + cAno);
187: break;
188: }
189: case TTiposDadoEDI.ediHoraHHMM:
190: {
191: string cHora = "";
192: string cMinuto = "";
193: if (this._SeparadorHora != null)
194: {
195: string[] split = this._ValorFormatado.Split(this._SeparadorHora.ToCharArray());
196: cHora = split[0];
197: cMinuto = split[1];
198: }
199: else
200: {
201: cHora = this._ValorFormatado.Substring(0, 2);
202: cMinuto = this._ValorFormatado.Substring(2, 2);
203: }
204: this._ValorNatural = DateTime.Parse(cHora + ":" + cMinuto + ":00");
205: break;
206: }
207: case TTiposDadoEDI.ediHoraHHMMSS:
208: {
209: string cHora = "";
210: string cMinuto = "";
211: string cSegundo = "";
212: if (this._SeparadorHora != null)
213: {
214: string[] split = this._ValorFormatado.Split(this._SeparadorHora.ToCharArray());
215: cHora = split[0];
216: cMinuto = split[1];
217: cSegundo = split[2];
218: }
219: else
220: {
221: cHora = this._ValorFormatado.Substring(0, 2);
222: cMinuto = this._ValorFormatado.Substring(2, 2);
223: cSegundo = this._ValorFormatado.Substring(4, 2);
224: }
225: this._ValorNatural = DateTime.Parse(cHora + ":" + cMinuto + ":00");
226: break;
227: }
228: case TTiposDadoEDI.ediDataDDMMAAAAWithZeros:
229: {
230: goto case TTiposDadoEDI.ediDataDDMMAAAA;
231: }
232: case TTiposDadoEDI.ediDataAAAAMMDDWithZeros:
233: {
234: goto case TTiposDadoEDI.ediDataAAAAMMDD;
235: }
236: }
237: }
238: }
Note que trabalhamos essencialmente com a conversão da string contida em ValorFormatado (obtida através da leitura do arquivo, que será detalhada na segunda parte
do artigo) nos tipos de dado correspondente à máscara informada, e retornando este objeto na propriedade ValorNatural.
Pronto, temos construída a classe que irá representar cada campo de um registro em um arquivo fixo-blocado. Note que esta classe é genérica, não foi informado nenhum atributo específico do layout que iremos construir, falado no início do artigo. Na segunda parte, vamos aplicar o conceito de POO sobre um registro de um arquivo.
Longo (principalmente os code-snippets :-)), não foi? Embora possamos fazer o proposto via ODBC (ainda não testei como se faz), esta série de artigos é mais para a aplicação do conceito de POO mesmo, embora eu já me utilizei deste código em alguns sistemas em produção :-)
Um abraço!
0 comentários:
Postar um comentário