Como crear macro para importar columnas de excel a DBF
"para Dante Amor", actualmente cuento con una macro para exportar a TXT, pero quiero saber como sería para exportar la misma información pero en formato .DBF
Sub ExportarArchivo()
'Por.Dante Amor
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Set l1 = ThisWorkbook
Set h1 = l1.ActiveSheet
'
FileName = Application.GetSaveAsFilename(InitialFileName:=vbNullString, FileFilter:="Text Files (*.txt),*.txt")
If FileName = False Then Exit Sub
'
ruta = l1.Path & "\"
h1.Copy
Set l2 = ActiveWorkbook
Set h2 = l2.Sheets(1)
cols = Array(6, 3, 10, 6, 4, 1, 4, 8, 40, 40, 35, 8)
h2.Rows(1).Delete
For i = LBound(cols) To UBound(cols)
h2.Columns(i + 1).ColumnWidth = cols(i)
Next
l2.SaveAs FileName:=FileName, FileFormat:=xlTextPrinter, CreateBackup:=False
l2.Close
MsgBox "Archivo creado"
End Sub
1 Respuesta
Te pongo un enlace para convertirlo desde access
http://thundaxsoftware.blogspot.mx/2009/07/convertir-ficheros-excel-2007-dbase-dbf.html
Encontré una macro para convertir los datos de la hoja de excel 2007 a dbf.
Como podrás observar, no es algo sencillo. Probé la macro para generar un archivo dbf, me parece que es para versión DBASE IV.
No tengo DBASE IV, por lo tanto no puedo abrir el archivo para revisarlo, pero te dejo el código para que lo pruebes.
Sub savedbf() Dim filename As Variant Dim temp As Variant Dim currentFile As String Dim defaultFile As String currentFile = ActiveWorkbook.Name temp = Split(currentFile, ".") temp(UBound(temp)) = "dbf" defaultFile = Join(temp, ".") If defaultFile = "dbf" Then defaultFile = ActiveWorkbook.Name & ".dbf" End If filename = Application.GetSaveAsFilename(InitialFileName:=defaultFile, FileFilter:="DBF 4 (dBASE IV) (*.dbf),*.dbf", Title:="Save As DBF") If filename = False Then Exit Sub Call DoSaveDefault(filename) End Sub Function DoSaveDefault(ByVal filename As String) ' Declare DB vars Dim path As Variant Dim file As Variant Dim tfile As Variant Dim table As Variant 'Dim dbConn As ADODB.Connection ' Initialize DB vars path = Split(filename, "\") file = path(UBound(path)) file = Replace(Left(file, Len(file) - 4), ".", "_") & Right(file, 4) tfile = "__T_DB__.dbf" path(UBound(path)) = "" path = Join(path, "\") table = Left(tfile, 8) filename = path & file ' Check if file exists On Error Resume Next GetAttr filename If Err.Number = 0 Then Dim mbResult As VbMsgBoxResult mbResult = MsgBox("The file " & file & " already exists. Do you want to replace the existing file?", _ VbMsgBoxStyle.vbYesNo + VbMsgBoxStyle.vbExclamation, "File Exists") If mbResult = vbNo Then DoSaveDefault = False Exit Function Else SetAttr filename, vbNormal Kill filename End If End If Err.Number = 0 GetAttr filename If Err.Number = 0 Then MsgBox "Unable to remove existing file " & file & ".", vbExclamation, "Error Removing File" DoSaveDefault = False Exit Function End If On Error GoTo 0 ' Open DB connection 'Set dbConn = New ADODB.Connection Set dbConn = CreateObject("adodb.connection") dbConn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & path & ";Extended Properties=""DBASE IV;"";" ' Declare excel vars Dim dataRange As Range Set dataRange = Selection If dataRange.Areas.Count > 1 Then MsgBox "The command you chose cannot be performed with multiple selections. Select a single range and click the command again.", _ VbMsgBoxStyle.vbCritical, "Error Saving File" DoSaveDefault = False Exit Function End If ' Expand selection if single cell (Expands selection using the Excel 2003 save DBF behavior) 'If dataRange.Cells.Count = 1 Then ' If IsEmpty(dataRange.Cells(1).Value) Then ' MsgBox "The command could not be completed by using the range specified. Select a single cell within the range and try the command again.", _ ' VbMsgBoxStyle.vbExclamation, "Error Saving File" ' DoSaveDefault = False ' Exit Function ' Else ' Set dataRange = dataRange.CurrentRegion ' End If 'End If ' Expand selection if single cell (Differs from normal Excel 2003 behavior by not stopping at blank rows and columns) If dataRange.Cells.Count = 1 Then Dim row1 As Integer Dim rowN As Integer Dim col1 As Integer Dim colN As Integer Dim cellFirst As Range Dim cellLast As Range row1 = ActiveSheet.Cells.Find(What:="*", SearchOrder:=xlByRows, SearchDirection:=xlNext).row col1 = ActiveSheet.Cells.Find(What:="*", SearchOrder:=xlByColumns, SearchDirection:=xlNext).Column rowN = ActiveSheet.Cells.Find(What:="*", After:=[A1], SearchOrder:=xlByRows, SearchDirection:=xlPrevious).row colN = ActiveSheet.Cells.Find(What:="*", After:=[A1], SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column Set cellFirst = ActiveSheet.Cells(row1, col1) Set cellLast = ActiveSheet.Cells(rowN, colN) Set dataRange = ActiveSheet.Range(cellFirst.Address, cellLast.Address) End If ' Declare data vars Dim i As Integer Dim j As Integer Dim numCols As Integer Dim numDataCols As Integer Dim numRows As Long Dim createString As String Dim fieldpos(), fieldvals(), fieldtypes(), fieldnames(), fieldactive() numCols = dataRange.Columns.Count numDataCols = 0 numRows = dataRange.Rows.Count ReDim fieldtypes(0 To numCols - 1) ReDim fieldnames(0 To numCols - 1) ReDim fieldactive(0 To numCols - 1) ' Fill field names i = 0 For Each c In dataRange.Rows(1).Columns ' Mark column active if not blank If WorksheetFunction.CountA(c.EntireColumn) > 0 Then fieldactive(i) = True numDataCols = numDataCols + 1 If VarType(c.Value) = vbString Then fieldnames(i) = Left(Replace(c.Value, " ", "_"), 10) Else fieldnames(i) = "N" & c.Column End If Else fieldactive(i) = False End If i = i + 1 Next ' Fill field positions ReDim fieldpos(0 To numDataCols - 1) ReDim fieldvals(0 To numDataCols - 1) For i = 0 To numDataCols - 1 fieldpos(i) = i Next ' Fill field types If dataRange.Rows.Count < 2 Then For i = 0 To numCols - 1 If fieldactive(i) Then fieldtypes(i) = vbString End If Next Else i = 0 For Each c In dataRange.Rows(2).Columns If fieldactive(i) Then fieldtypes(i) = VarType(c.Value) End If i = i + 1 Next End If ' Create table Dim cat As ADOX.Catalog Dim tbl As ADOX.table Dim col As ADOX.Column Set cat = New ADOX.Catalog cat.ActiveConnection = dbConn Set tbl = New ADOX.table tbl.Name = table For i = 0 To numCols - 1 ' Only add non-blank columns If fieldactive(i) Then Set col = New ADOX.Column col.Name = fieldnames(i) fillColumnType col, fieldtypes(i), dataRange.Columns(i + 1) tbl.Columns.Append col Set col = Nothing End If Next On Error Resume Next cat.Tables.Delete table On Error GoTo 0 cat.Tables.Append tbl ' Populate table 'Dim rs As ADODB.Recordset Dim r As Range Dim row As Long 'Set rs = New ADODB.Recordset Set rs = CreateObject("adodb.recordset") rs.Open table, dbConn, adOpenDynamic, adLockPessimistic, adCmdTable If rs.LockType = LockTypeEnum.adLockReadOnly Then MsgBox "The recordset is read-only.", vbExclamation, "Error Inserting Record" End If For row = 2 To numRows Set r = dataRange.Rows(row) ' Only add non-blank rows If WorksheetFunction.CountA(r.EntireRow) > 0 Then i = 0 j = 0 For Each c In r.Cells If fieldactive(i) Then fieldvals(j) = getValByVbType(c.Text, fieldtypes(i)) j = j + 1 End If i = i + 1 Next rs.AddNew fieldpos, fieldvals End If Next ' Close the recordset and connection Rs. Close DbConn. Close ' Copy file to final destination (this is necessary because the Jet driver limits ' the filename to 8 chars before the extension) 'Dim fs As Scripting. FileSystemObject 'Set fs = New Scripting.FileSystemObject 'fs.CopyFile path & tfile, filename FileCopy path & tfile, filename 'Set fs = Nothing Kill path & tfile DoSaveDefault = True End Function Function fillColumnType(col As ADOX.Column, ByVal vtype As Integer, colrange As Range) As Boolean Select Case vtype Case vbInteger, vbLong, vbByte col.Type = adInteger Case vbSingle, vbDouble, vbDouble fillColNumberType col, colrange Case vbCurrency col.Type = adCurrency Case vbDate col.Type = adDate Case vbBoolean col.Type = adBoolean Case vbString fillColStringType col, colrange Case Else col.Type = adWChar col.Precision = 32 End Select getAdoTypeFromVbType = True End Function Function getValByVbType(ByVal s As String, ByVal t As Integer) Dim result As Variant result = Null On Error Resume Next Select Case t Case vbInteger, vbLong, vbByte result = CInt(s) Case vbSingle, vbDouble, vbCurrency, vbDecimal If CInt(s) <> CDec(s) Then result = CDec(s) Else result = CInt(s) End If Case vbDate result = CDate(s) Case vbBoolean result = CInt(s) <> 0 Case vbString result = s Case Else result = Null End Select On Error GoTo 0 getValByVbType = result End Function Function fillColStringType(col As ADOX.Column, r As Range) As Boolean Dim lenshort As Integer Dim lenlong As Integer Dim l As Integer lenshort = Len(r.Cells(2).Text) lenlong = lenshort For Each c In r.Cells If c.row > 1 Then l = Len(c.Text) If l < lenshort Then lenshort = l End If If l > lenlong Then lenlong = l End If End If Next If lenlong > 254 Then col.Type = adLongVarWChar ElseIf lenlong > 128 And lenlong < 255 Then col.Type = adWChar col.Precision = 254 ElseIf lenshort = lenlong And lenlong < 17 Then col.Type = adWChar col.Precision = lenlong Else col.Type = adWChar col.Precision = ceilPow2(lenlong) End If fillColStringType = True End Function Function fillColNumberType(col As ADOX.Column, r As Range) As Boolean Dim hasDecimal As Boolean Dim t As Boolean hasDecimal = False On Error Resume Next For Each c In r.Cells If c.row > 1 Then t = Val(c.Text) <> Int(Val(c.Text)) If Err.Number = 0 And t Then hasDecimal = True Exit For End If End If Next On Error GoTo 0 If hasDecimal Then col.Type = adNumeric col.Precision = 11 col.NumericScale = 4 Else col.Type = adInteger End If fillColNumberType = True End Function Function ceilPow2(x As Integer) Dim i As Integer i = 2 Do While i < x i = i * 2 Loop ceilPow2 = i End Function
' : ) 'S aludos. Dante Amor. Recuerda valorar la respuesta. G racias ' : )
- Compartir respuesta