Eliminare righe in file txt



  • Eliminare righe in file txt
    di fabio (utente non iscritto) data: 08/09/2017 14:00:32

    Buongiorno,
    a volte ho la necessità di importare dei dati da un file txt che apro con una macro senza problemi.
    Il problema mi si crea quando il file txt ha più di 1.000.000 di righe ed excel non può contenerle.
    E' possibile eliminare delle righe direttamente nel file txt tutte le righe da una riga xxx in poi (sapendo che la riga xxx contiene una stringa unica e fissa "nxweb_dettaglio"), salvarlo per poi (diventando le righe inferiori a 1.000.000) riaprirlo importando i dati in Excel?
    Grazie



  • di patel data: 09/09/2017 06:05:40

    hai provato a fare una ricerca con google ? io ho trovato questo
    www.forumexcel.it/forum/6-domande-su-excel-in-generale/1703-importare-txt-oltre-numero-max-righe-excel
    senza disporre del tuo file di testo e della tua macro non posso fare di più





  • di fabio (utente non iscritto) data: 11/09/2017 09:59:20

    grazie patel per l'indicazione.
    avevo già fatto una ricerca su internet e avevo già letto anche quanto mi hai suggerito.
    Purtroppo non ho trovato la soluzione al mio problema (eliminare righe direttamente nel file txt).
    Provo a creare dei file ridotti da inserire.
    grazie



  • di fabio (utente non iscritto) data: 19/09/2017 15:06:58

    ciao patel,
    ecco finalmente i due file che ho creato per fare delle prove.
    Il primo (riduci file.xls) contiene la macro che mi apre il file txt estraendomi solo la parte che mi interessa.
    Il secondo (filetxt_ridotto.txt) è il file che vado ad aprire e dal quale vorrei eliminare delle righe prima di aprirlo con excel (essendo che il file originale contiene più di 1.000.000 di righe).
    In particolare dovrei eliminare le righe contenute tra le stringhe NXWEB_TITOLO e NXWEB_SIN_INCR_PRT (è un blocco con moltissime righe che non mi interessano).
    Grazie per l'interessamento



  • di patel data: 19/09/2017 16:20:39

    tu vorresti eliminare righe direttamente nel file txt, per fare ciò occorrerebbe leggerlo riga per riga, controllare la presenza delle parole che hai indicato e riscrivere un altro file privo di quel blocco. Quando le righe sono poche si può fare, altrimenti ci possono volere delle ore a risalvare il file, ti va bene così ?
    Usando invece la macro che ti ho indicato i tempi di caricamento ed individuazione delle parole chiave sono sicuramente più rapidi





  • di fabio (utente non iscritto) data: 19/09/2017 16:29:44

    pensavo, e speravo, che come per l'apertura si potesse individuare direttamente il blocco delle righe da eliminare (senza doverle leggere tutte).
    A quale macro ti riverisci quando mi scrivi "Usando invece la macro che ti ho indicato..." ?
    Grazie



  • di patel data: 19/09/2017 16:45:03

    la mia prima risposta
    www.forumexcel.it/forum/6-domande-su-excel-in-generale/1703-importare-txt-oltre-numero-max-righe-excel
    domanda: eliminando le righe inutili il numero di righe diventa < 1 milione ?





  • di fabio (utente non iscritto) data: 19/09/2017 17:09:11

    Si, perchè quel blocco contiene moltissime righe



  • di patel data: 19/09/2017 18:05:49

    prova questa, mette in colonna A le righe valide 
     
    Sub eliminarighe()
    Dim sh1 As Worksheet, fullnome As String, testo As String, inizio As Double
    Dim conta As Double, Ncolonne As Integer, riga As Long, Col As Long, domanda
    Dim i As Long, j As Long, matrice()
    Application.ScreenUpdating = False
    inizio = Timer
    With ThisWorkbook
      Set sh1 = .Worksheets("Foglio1")
    End With
    With Application.FileDialog(msoFileDialogFilePicker)
      .AllowMultiSelect = False
      .Filters.Clear
      .Filters.Add "All files", "*.*"
      .Filters.Add "text", "*.txt", 1
      .Show
      If .SelectedItems.Count = 0 Then
        MsgBox ("Nessuna voce selezionata, procedura annullata")
        GoTo esci
      End If
      fullnome = .SelectedItems(1)
    End With
    Open fullnome For Input As #1
    dr = 1
    trova = "NXWEB_TITOLO"
    flag = 1
    Do
        Line Input #1, testo
        If InStr(testo, trova) = 0 Then
          Cells(dr, 1) = testo
          dr = dr + 1
        Else
          Exit Do
        End If
    Loop
    trova = "NXWEB_SIN_INCR_PRT"
    While InStr(testo, trova) = 0
        Line Input #1, testo
    Wend
    While Not EOF(1)
        Line Input #1, testo
        Cells(dr, 1) = testo
        dr = dr + 1
    Wend
    Close #1
    esci:
    Application.ScreenUpdating = True
    MsgBox Timer - inizio & " secondi"
    End Sub






  • di Vecchio Frac data: 21/09/2017 20:46:37

    Peccato che non ho letto prima questa discussione, potevo suggerire il metodo con Get che è velocissimo (molto più di Line Input) e ha una limitazione (teorica) di 2GB di dati. Sarei curioso di vedere che risultati ottenete con i file reali.





  • di patel data: 22/09/2017 10:02:31

    intendi una cosa del genere ? non ci avevo pensato
     
    Sub ReadCsv1()
      Dim FileNum As Long, Filename As String, TotalFile As String, Records() As String
      Filename = "F:Downloadordini.csv" ' <<<<<<<< change it
      FileNum = FreeFile
      Open Filename For Binary As #FileNum
        TotalFile = Space(LOF(FileNum))
        Get #FileNum, , TotalFile
      Close #FileNum
      Records = Split(TotalFile, vbcrlf)
      ......
    End Sub






  • di Vecchio Frac data: 22/09/2017 10:33:07

    @patel
    +1
    Adesso in Records() abbiamo un array di stringhe facilmente manipolabile. Essendo in memoria anche le operazioni di ricerca e sostituzione sono molto rapide. Una volta fatte tutte operazioni di pulizia dovute, riversare il contenuto di Records() sul foglio o su un file (con Put) è molto facile.





  • di patel data: 22/09/2017 11:38:33

    aspettiamo i risultati di fabio, sembra sparito, forse è sempre lì che aspetta la fine dell'esecuzione della macro





  • di fabio (utente non iscritto) data: 22/09/2017 11:48:34

    Ciao Patel, ciao Vecchio Frac,
    no non sono sparito ma sono stato fuori ufficio e ho avuto solo poco tempo per provare la macro di patel (mi da errore su un file txt più grosso ma non fatto verifiche)
    Appena riesco riprovo il tutto e vi faccio sapere.
    Grazie mille



  • di fabio (utente non iscritto) data: 22/09/2017 13:36:44

    Rieccomi. Avendo un po' di tempo ho provato a completare la macro di patel con le indicazioni di vecchio frac ma sono troppo inesperto per riuscirci.
    Potete aiutarmi?
    Il mio obiettivo è:
    - leggere il file txt,
    - individuare il blocco delle righe tra le stringhe NXWEB_TITOLO e
    - eliminare le righe individuate
    - creare un nuovo file txt che (se eliminate le righe) risulta leggibile senza problemi.
    Grazie ancora per la vostra disponibilità.



  • di Vecchio Frac data: 22/09/2017 14:42:47

    Non so, una soluzione potrebbe essere questa.
     
    Option Explicit
    
    
    Sub eliminarighe()
    Dim fullnome As String, inizio As Double
    Dim FileNum As Long, TotalFile As String, Records() As String
    Dim deletable As Boolean, s As String
    Dim i As Long
    Dim rec As Variant
        
        Application.ScreenUpdating = False
        inizio = Timer
        
        With Application.FileDialog(msoFileDialogFilePicker)
            .AllowMultiSelect = False
            .Filters.Clear
            .Filters.Add "All files", "*.*"
            .Filters.Add "text", "*.txt", 1
            .Show
            If .SelectedItems.Count = 0 Then
                MsgBox "Nessuna voce selezionata, procedura annullata"
                Application.ScreenUpdating = True
                MsgBox Timer - inizio & " secondi"
                Exit Sub
            End If
            fullnome = .SelectedItems(1)
        End With
        
        FileNum = FreeFile
        Open fullnome For Binary As #FileNum
        TotalFile = Space(LOF(FileNum))
        Get #FileNum, , TotalFile
        Close #FileNum
        Records = Split(TotalFile, vbCrLf)
        
        deletable = False
        For Each rec In Records
            If InStr(rec, "NXWEB_TITOLO") > 0 Then deletable = True: Debug.Print "NXWEB_TITOLO at index " & i
            If InStr(rec, "NXWEB_SIN_INCR_PRT") > 0 Then deletable = False: Debug.Print "NXWEB_SIN_INCR_PRT at index " & i
            If Not deletable Then s = s & vbCrLf & rec
            i = i + 1
        Next
        Close
        
        Open fullnome & "_reduced.txt" For Binary As #FileNum
        Put #1, , s & vbCrLf
        Close
        
        
        Application.ScreenUpdating = True
        MsgBox "Finito in " & Timer - inizio & " secondi"
    End Sub






  • di fabio (utente non iscritto) data: 22/09/2017 16:08:52

    con un file txt di medie dimensioni (tipo quello allegato) o anche più grande è perfetto.
    L'ho provato su un file molto grande ma va in errore sulla riga "TotalFile = Space(LOF(FileNum))" con il messaggio "Errore di run-time 14 - Spazio stringa esaurito".
    Si riesce a fare qualcosa visto che mi serve proprio per un file grande?
    Grazie mille



  • di Vecchio Frac data: 22/09/2017 16:14:48

    Quel "molto grande" mi fa supporre che veramente stiamo parlando di un file di molti mega o addirittura giga.
    Conviene separare in pezzi più piccoli il file originale e processarli singolarmente.
    Ti scrivo velocemente uno spezzone di codice che spezza una stringa di testo grande in pezzi più piccoli (e genera file ridotti), a blocchi di 4000 righe alla volta. La cosa però va studiata con calma e tempo, che adesso non ho :)
     
        j = 0
        For i = 1 To 5
            Open "C:UsersPippoDesktop	est_" & i & ".txt" For Binary As #1
            For chunk = j + 0 To j + 3999
                MyData = strData(chunk)
                Put #1, , MyData & vbCrLf
            Next
            j = j + 4000
            Close #1
        Next






  • di fabio (utente non iscritto) data: 22/09/2017 16:19:54

    purtropo si, è un file da quasi 200 mega e con più 1.200.000 righe.
    grazie



  • di Vecchio Frac data: 22/09/2017 21:33:08

    Fammi una prova col codice seguente, che utilizza un FileSystemObject per leggere il file in memoria.
    E' circa quattro volte più lento del precedente e probabilmente darà lo stesso tipo di errore (memoria esaurita) quando tenterà di assegnare a TotalFile il contenuto del file con ReadAll. Ma è solo una curiosità.
    L'ultima soluzione prevede la lettura sequenziale (vedi soluzione patel) o a blocchi (da implementare).
     
    Option Explicit
    
    
    Sub eliminarighe()
    Dim fullnome As String, inizio As Double
    Dim FileNum As Long, TotalFile As String, Records() As String
    Dim deletable As Boolean, s As String
    Dim i As Long
    Dim rec As Variant
    Dim fso As Object, objTextFile As Object
    
    Const ForReading As Integer = 1
    
        Application.ScreenUpdating = False
        inizio = Timer
        
        With Application.FileDialog(msoFileDialogFilePicker)
            .AllowMultiSelect = False
            .Filters.Clear
            .Filters.Add "All files", "*.*"
            .Filters.Add "text", "*.txt", 1
            .Show
            If .SelectedItems.Count = 0 Then
                MsgBox "Nessuna voce selezionata, procedura annullata"
                Application.ScreenUpdating = True
                MsgBox Timer - inizio & " secondi"
                Exit Sub
            End If
            fullnome = .SelectedItems(1)
        End With
        
        Set fso = CreateObject("Scripting.FileSystemObject")
        Set objTextFile = fso.OpenTextFile(fullnome, ForReading)
        TotalFile = objTextFile.ReadAll
        objTextFile.Close
        Records = Split(TotalFile, vbCrLf)
        
        deletable = False
        For Each rec In Records
            If InStr(rec, "NXWEB_TITOLO") > 0 Then deletable = True: Debug.Print "NXWEB_TITOLO at index " & i
            If InStr(rec, "NXWEB_SIN_INCR_PRT") > 0 Then deletable = False: Debug.Print "NXWEB_SIN_INCR_PRT at index " & i
            If Not deletable Then s = s & vbCrLf & rec
            i = i + 1
        Next
        Close
        
        Open fullnome & "_reduced.txt" For Binary As #1
        Put #1, , s & vbCrLf
        Close
        
        
        Application.ScreenUpdating = True
        MsgBox "Finito in " & Timer - inizio & " secondi"
    End Sub
    






  • di fabio (utente non iscritto) data: 25/09/2017 14:06:07

    ho provato sul un file di media grandezza la nuova macro che non mi ha dato errori ma ha impiegato 287 secondi.
    Quondo l'ho provata sul file di grandi dimensioni, mi ha dato un errore (vedi allegato)



  • di oregon (utente non iscritto) data: 25/09/2017 19:19:16

    1) il blocco da eliminare si presenta una sola volta o si può presentare più volte?

    2) il file più grande che tratti di che lunghezza è?

    3) è possibile avere questo file (il più grande) magari zippato da scaricare?

    4) usi sistemi a 32 bit?



  • di Vecchio Frac data: 25/09/2017 21:59:25

    Intanto che rispondi a oregon ti faccio fare un altro test ^_^
     
    Option Explicit
    
    Sub eliminarighe()
    Dim fullnome As String, inizio As Double
    Dim s As String
    Dim i As Long, j As Long
    Dim wdApp As Object
    Dim wdDoc As Object
    
    Const ForReading As Integer = 1
    
        Application.ScreenUpdating = False
        inizio = Timer
        
        With Application.FileDialog(msoFileDialogFilePicker)
            .AllowMultiSelect = False
            .Filters.Clear
            .Filters.Add "All files", "*.*"
            .Filters.Add "text", "*.txt", 1
            .Show
            If .SelectedItems.Count = 0 Then
                MsgBox "Nessuna voce selezionata, procedura annullata"
                Application.ScreenUpdating = True
                MsgBox Timer - inizio & " secondi"
                Exit Sub
            End If
            fullnome = .SelectedItems(1)
        End With
    
        Set wdApp = CreateObject("Word.Application")
        Set wdDoc = wdApp.Documents.Open(fullnome)
        
        'find start
        wdDoc.Bookmarks("StartOfDoc").Select
        wdApp.Selection.Find.Execute FindText:="NXWEB_TITOLO"
        i = wdApp.Selection.Start
        wdApp.Selection.MoveRight
    
        'find end
        wdApp.Selection.Find.Execute FindText:="NXWEB_SIN_INCR_PRT"
        j = wdApp.Selection.End
        
        'delete range
        wdDoc.Range(Start:=i, End:=j).Delete
        
        'save file
        wdDoc.SaveAs fullnome & "_ridotto.txt"
        
        wdDoc.Close
        wdApp.Quit
        Set wdDoc = Nothing
        Set wdApp = Nothing
    
    End Sub






  • di Fabio (utente non iscritto) data: 26/09/2017 16:59:13

    @ oregon
    1) - si, il blocco si presenta una sola volta
    2) - l'attuale file sono circa 1.200.000 righe e 195 mega di dimensione
    3) - anche zippato sono circa 70 mega - se può essere utile posso creare un file con le stesse righe ma meno dati e quindi più piccolo
    4) - uso sia a 32 che a 64 bit

    @ Vecchio Frac
    ho provato la nuova macro sul file "medio e funziona perfettamente ed è anche molto più veloce ma sul file grande mi crea un nuovo file ma senza eliminare le righe. Sto facendo altre prove per vedere se riesco a capire come mai.
    Grazie



  • di oregon (utente non iscritto) data: 26/09/2017 17:10:21

    1) Quanto è più veloce con l'ultima macro (con Word)?

    2) Puoi farmi scaricare il file completo zippato (da dropbox o simili non sono molti 70 M)




  • di oregon (utente non iscritto) data: 26/09/2017 17:12:02

    Dimenticavo ... tu non sai dove si presenta il blocco, ovvero non ha posizioni fisse, né l'inizio né la fine. Giusto?



  • di Fabio (utente non iscritto) data: 26/09/2017 17:26:45

    - con la nuova macro ci ha messo circa 15 secondi prima erano 287 (sempre sul file medio)
    - potrei farti scaricare il file tramite wetransfert ma mi serve l'indirizzo e-mail
    - la stringa di inizio e di fine sono sempre le stesse ma cambiano le righe



  • di Vecchio Frac data: 26/09/2017 20:00:40

    cit. "mi crea un nuovo file ma senza eliminare le righe"
    ---> Probabilmente è più veloce il comando di chiusura (WdDoc.Close) che quello di salvataggio (wdDoc.SaveAs).
    Come ultimo tentativo, sotto SaveAs puoi impostare un'istruzione che ferma l'esecuzione finchè non è completato il salvataggio. Ad esempio Application.Wait (Now + TimeValue("00:00:05") per stoppare cinque secondi.
    Mi viene in mente anche di farti inserire un DoEvents() prima del SaveAs.
    Suggerimenti a naso, vista l'indisponibilità di un file così grande per le prove :)
    Comunque sono curioso di conoscere i suggerimenti di oregon.

    ps le alternative ci sono e anche più efficienti, ma coinvolgono altri linguaggi di programmazione ^_^





  • di oregon (utente non iscritto) data: 27/09/2017 00:36:13

    Pensavo di usare i memory mapped file.

    Mappando in memoria il file, anche se molto grande, il lavoro di ricerca e spostamento dei dati può avvenire velocemente (con API opportune). Infine, il file può essere semplicemente ridimensionato.

    Non ho fatto tante prove e quindi potrebbero esserci degli aggiustamenti da fare.

    Ho creato un file da circa 200 M e ho rilevato tempi di 1 o 2 secondi.

    Tutto da testare.
     
    Public Const PAGE_READWRITE As Long = &H4
    Public Const FILE_MAP_WRITE As Long = &H2
    Public Const GENERIC_READ = &H80000000
    Public Const GENERIC_WRITE = &H40000000
    Public Const OPEN_ALWAYS = 4
    Public Const FILE_ATTRIBUTE_NORMAL = &H80
    Public Const FILE_BEGIN = 0
    
    Public hFileMap As Long
    Public hMM As Long
    Public mapped_file As String
    Public bound As Long
    
    Public Declare Function GetFileSize Lib "Kernel32" ( _
        ByVal hFile As Long, lpFileSizeHigh As Long) As Long
    
    Public Declare Function SetFilePointer Lib "Kernel32" ( _
        ByVal hFile As Long, _
        ByVal lDistanceToMove As Long, _
        lpDistanceToMoveHigh As Long, _
        ByVal dwMoveMethod As Long) As Long
    
    Public Declare Function SetEndOfFile Lib "Kernel32" ( _
        ByVal hFile As Long) As Long
    
    Public Declare Function CreateFile Lib "Kernel32" Alias "CreateFileA" (ByVal lpFileName As String, _
        ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, _
        ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, _
        ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
    
    Public Declare Function CreateFileMapping Lib "kernel32.dll" Alias "CreateFileMappingA" ( _
         ByVal hFile As Long, _
         ByVal lpFileMappigAttributes As Long, _
         ByVal flProtect As Long, _
         ByVal dwMaximumSizeHigh As Long, _
         ByVal dwMaximumSizeLow As Long, _
         ByVal lpName As String) As Long
    
    Public Declare Function MapViewOfFile Lib "kernel32.dll" ( _
         ByVal hFileMappingObject As Long, _
         ByVal dwDesiredAccess As Long, _
         ByVal dwFileOffsetHigh As Long, _
         ByVal dwFileOffsetLow As Long, _
         ByVal dwNumberOfBytesToMap As Long) As Long
    
    Public Declare Function UnmapViewOfFile Lib "kernel32.dll" ( _
        ByVal lpBaseAddress As Any) As Long
    
    Public Declare Function CloseHandle Lib "kernel32.dll" ( _
        ByVal hObject As Long) As Long
    
    Public Declare Function ReadFile Lib "kernel32.dll" ( _
        ByVal hFile As Long, _
        ByRef lpBuffer As Any, _
        ByVal nNumberOfBytesToRead As Long, _
        ByRef lpNumberOfBytesRead As Long, _
        ByVal lpOverlapped As Long) As Long
    
    Public Declare Sub MoveMemory Lib "Kernel32" Alias "RtlMoveMemory" ( _
        ByVal Destination As Long, _
        ByVal Source As Long, _
        ByVal Length As Long)
    
    Public Declare Function MemCmp Lib "ntdll" Alias "RtlCompareMemory" ( _
        ByVal Source1 As Long, Source2 As Any, _
        ByVal Length As Long) As Long
        
    Public Declare Function StrStr Lib "shlwapi.dll" Alias "StrStrA" ( _
        ByVal lpszMin As Long, lpszSearch As Any) As Long
    
    ''''
        Dim byFrom() As Byte
        Dim byFromLen As Long
        byFrom = StrConv("NXWEB_TITOLO" & Chr(0), vbFromUnicode)
        byFromLen = UBound(byFrom)
        
        Dim byTo() As Byte
        Dim byToLen As Long
        byTo = StrConv("NXWEB_SIN_INCR_PRT" & Chr(0), vbFromUnicode)
        byToLen = UBound(byTo)
        
        Dim hFile As Long
        hFile = CreateFile("File.txt", GENERIC_READ Or GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)
        
        Dim fLen As Long
        fLen = GetFileSize(hFile, 0)
        
        Dim hFileMap As Long
        hFileMap = CreateFileMapping(hFile, 0, PAGE_READWRITE, 0, 0, 0)
        
        Dim hMM As Long
        hMM = MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0)
        
        Dim pFrom As Long
        pFrom = StrStr(hMM, byFrom(0))
        SetFilePointer hFile, pFrom - hMM, 0, FILE_BEGIN
        
        Dim Ret As Long
        Dim TxtBytes() As Byte
        Dim s As String
        
        ReDim TxtBytes(byFromLen) As Byte
        ReadFile hFile, TxtBytes(0), byFromLen, Ret, 0
        s = StrConv(TxtBytes, vbUnicode)
        
        Dim pTo As Long
        pTo = StrStr(pFrom, byTo(0))
        SetFilePointer hFile, pTo - hMM, 0, FILE_BEGIN
        
        ReDim TxtBytes(byToLen) As Byte
        ReadFile hFile, TxtBytes(0), byToLen, Ret, 0
        s = StrConv(TxtBytes, vbUnicode)
        
        Dim pLen As Long
        pLen = fLen + hMM - pTo - 1
        MoveMemory pFrom, pTo, pLen
        
        UnmapViewOfFile (hMM)
        CloseHandle hFileMap
        
        SetFilePointer hFile, fLen - (pTo - pFrom - 1), 0, FILE_BEGIN
        SetEndOfFile hFile
        
        CloseHandle hFile
    
    



  • di Vecchio Frac data: 27/09/2017 08:39:50

    Interessante, mai utilizzata questa tecnica, mi copio il post per il futuro ^_^
    Adesso attendiamo il test di Fabio.





  • di oregon (utente non iscritto) data: 27/09/2017 09:05:12

    Qualche precisazione ..

    Le parti riguardanti le ReadFile sono inserite solo per controllo ma non sono necessarie.

    Il risultato delle chiamate delle API non è controllato. Andrebbe fatto perché le chiamate successive possono creare un crash di tutto Excel.




  • di fabio (utente non iscritto) data: 27/09/2017 13:38:10

    volevo fare una prova ed ho copiato il tutto in una macro (vedi allegato) ma sicuramente sbaglio qualcosa o devo cambiare dei parametri.
    Ho provato a lanciarla ma apperentemente non fa nulla e non mi chiede il file da aprire.
    Purtroppo non sono in grado di intervenire. Mi aiuti?
    Grazie



  • di oregon (utente non iscritto) data: 27/09/2017 14:13:26

    Non ti chiede il file da aprire perché non c'è questa parte di codice.

    Il codice è relativo solo alle operazioni di ricerca ed eliminazione del blocco che avevi chiesto. Per farlo ho inserito (non l'hai visto) un nome di file fisso e di prova ("File.txt") nel codice.

    Devi provvedere tu ad aggiungere, se vuoi, il codice con cui scegli il file e passarlo in una variabile al posto di "File.txt".

    Non pensavo che tu fossi completamente a zero a livello di codice.



  • di oregon (utente non iscritto) data: 27/09/2017 14:16:44

    Puoi prendere la parte di codice che ti serve dalle altre soluzioni proposte.

    Mi riferisco, ad esempio, al blocco che inizia con

    With Application.FileDialog(msoFileDialogFilePicker)

    e usare la variabile fullnome per il nome completo del file selezionato da passare al resto del codice.



  • di fabio (utente non iscritto) data: 27/09/2017 14:19:03

    purtroppo si, magari non a zero ma a 0,1
    ci provo e ti faccio sapere
    grazoe



  • di oregon (utente non iscritto) data: 27/09/2017 14:23:09

    Per fare una prova veloce (che è quello che interessa attualmente) sostituisci a

    "File.txt"

    il percorso e il nome del tuo file, ad esempio

    "C:Cartella1Cartella2Dati.xyz"

    e vedi cosa succede.



  • di fabio (utente non iscritto) data: 27/09/2017 15:02:02

    ho fatto una prova sul file medio ed è velocissimo e tutto ok.
    Sul file grande excel smette di funzionare e si chiude.
    Ho provato riga per riga e va in errore alla riga MoveMemory pFrom, pTo, pLen (vedi allegato doc2)



  • di oregon (utente non iscritto) data: 27/09/2017 15:24:16

    Con il file grande hai provato aprendo excel o dopo aver operato con il file piccolo?

    Comunque bisognerebbe disporre del file grande come ti avevo detto.
    Dovresti metterlo su un dropbox e darci il link per provare



  • di fabio (utente non iscritto) data: 27/09/2017 15:50:09

    immaginando che fosse un problema di memoria ho provato a chiudere tutto e riaprire excel ma non è cambiato.
    essendo che il file grande contine molti dati (forse anche sensibili) come faccio a farti aver il link privatamente?



  • di oregon (utente non iscritto) data: 27/09/2017 16:27:19

    Mandami il link da cui scaricare il file (non il file perché la posta non lo supporterebbe) all'indirizzo temporaneo di posta

    Sernis1984 AT teleworm.us

    Mandalo prima possibile perché domani non potrò lavorarci.



  • di fabio (utente non iscritto) data: 27/09/2017 16:45:07

    ti sto inviato il link per scaricare il file tramite wetransfert.
    volevo segnalati che nel file che ti ho inviato il blocco delle righe da eliminare si trova tra le stringhe NXWEB_TITOLO e NXWEB_SINISTRIC_SIN
    dovresti aver già ricevuto il link
    il file zippato è di circa 36 mb



  • di oregon (utente non iscritto) data: 27/09/2017 16:50:37

    Ma tu hai cambiato nel codice la stringa che avevi detto prima con

    NXWEB_SINISTRIC_SIN

    prima di provarlo?



  • di fabio (utente non iscritto) data: 27/09/2017 16:53:42

    si certo



  • di oregon (utente non iscritto) data: 27/09/2017 17:06:56

    Guarda che non esiste la parola

    NXWEB_SINISTRIC_SIN

    nel testo ma sono due termini separati da un "a capo"

    NXWEB_SINISTRI
    C_SIN

    che è diverso.

    Riprova con

    NXWEB_SINISTRI

    mi sembra lo stesso.



  • di Fabio (utente non iscritto) data: 27/09/2017 17:18:27

    Con il cerca del edit l’aveva trovata
    Ora sono in auto. Più tardi riprovo



  • di oregon (utente non iscritto) data: 27/09/2017 17:22:18

    Anche io l'ho trovato ma con un a capo tra le due parti.



  • di oregon (utente non iscritto) data: 27/09/2017 17:27:41

    Ti confermo, l'editor binario riporta un linefeed (0A) tra le due parole

    4E 58 57 45 42 5F 53 49 4E 49 53 54 52 49 0A NXWEB_SINISTRI
    43 5F 53 49 4E C_SIN



  • di oregon (utente non iscritto) data: 27/09/2017 17:58:40

    Errata corrige:

    due linee da modificare nel codice ...

    Subito prima della MoveMemory (la formula per la pLen) e nella SetFilePointer, ovvero


     
    pLen = fLen + hMM - pTo 
        
    ...
    
    SetFilePointer hFile, fLen - (pTo - pFrom), 0, FILE_BEGIN



  • di FABIO (utente non iscritto) data: 27/09/2017 21:47:36

    è perfetto e velocissimo. Ora il file contiene meno di 1.000.000 di righe e posso aprilo con excel.
    Ora mi divertirò (spero) ad adattarlo al meglio al mio progetto.
    grazie infinite e complimenti per la vostra preparazione e perspicacia.
    Grazie mille anche a Vecchio Frac e a patel per il loro interessamento.



  • di oregon (utente non iscritto) data: 27/09/2017 21:54:53

    Di nulla ... Ciao



  • di patel data: 28/09/2017 10:04:22

    Ciao Oregon, scrivi anche sulla sezione vb.net di Forum.html.it ?
    Complimenti per l'ottimo lavoro !
    Il tuo codice modifica direttamente il file di origine, come deve essere modificato per salvare con altro nome ?






  • di oregon (utente non iscritto) data: 28/09/2017 10:36:51

    Non puoi salvare su altro file perché le operazioni sono fatte tutte sul file originale.

    Certo che scrivo in quel forum e in altri ma tu mi conosci come AntonioG



  • di patel data: 28/09/2017 11:27:36

    OK, grazie, basta farne prima una copia.





  • di fabio (utente non iscritto) data: 28/09/2017 13:27:59

    Ciao Oregon, scusa ma come al solito l'appetito vien mangiando....
    mi chiedevo e quindi ti chiedo se anzichè eliminare le righe del blocco identificato fosse possibile eliminare tutte le righe a partire dalla prima stringa identificata fino alla fine del file.
    Purtroppo alla fine del file non c'è una stringa fissa e univoca da poter richiamare
    Grazie ancora



  • di oregon (utente non iscritto) data: 28/09/2017 13:56:19

    Certo che si può ed è una modifica banale. Però adesso non posso darti i dettagli, se qualcuno non lo farà prima, vedrò se posso stasera



  • di Vecchio Frac data: 28/09/2017 15:34:28

    cit. " tu mi conosci come AntonioG"
    ---> G come Giuliana? sarebbe un enorme onore avere qui un mostro del calibro di Antonio Giuliana ^_^

    Se non è così, grazie comunque del tuo prezioso e valido contributo (anche se a me in verità il tuo codice non funziona perchè GetFileSize mi restituisce sempre un valore 2 o 3 a seconda delle dimensioni del mio file di testo di prova, circa 591 MB).





  • di oregon (utente non iscritto) data: 28/09/2017 17:40:48

    Grazie ma mostruoso è esagerato ... É proprio quella la G ...

    Sono di passaggio perché ho visto che c'era un problema interessante ... Come sai ho già parecchi impegni sugli altri forum ... Comunque siete voi i veri mostri del forum..
    Per il tuo problema, per me il programma non trova o non ha i diritti per accedere al file. Devi controllare il valore restituito dalla CreateFile



  • di Vecchio Frac data: 28/09/2017 17:50:16

    Un campione di umiltà... io ti conosco dai trascorsi su VBT&T (e se qui mai leggessi anche il nome di Diego sarebbe festa nazionale... ma lasciamo che si goda la pensione ^_^).
    Grande Antonio, ti auguro un buon lavoro e se puoi ogni tanto torna.
    Avrei un quesito piuttosto tecnico ma non voglio disturbarti oltre ^_^





  • di oregon (utente non iscritto) data: 28/09/2017 19:28:54

    Bei tempi ... Se ti posso dare una mano chiedi come ti viene meglio...



  • di oregon (utente non iscritto) data: 29/09/2017 09:35:29

    Come ti avevo detto, il codice che limita il file da un punto alla fine è più semplice ed è quello che ti mostro di seguito.

    Attenzione che, anche in questo caso, non sono stati fatti i controlli dopo le chiamate delle API e potresti avere problemi se il dato non viene trovato. Ad esempio, il file potrebbe crescere di dimensioni in maniera strana (ma perfettamente spiegabile).
     
        Dim hFile As Long
        Dim fLen As Long
        
        Dim byFrom() As Byte
        Dim byFromLen As Long
        byFrom = StrConv("NXWEB_TITOLO" & Chr(0), vbFromUnicode)
        byFromLen = UBound(byFrom)
        
        hFile = CreateFile("C:Usersgiuliana_a.AMMDesktopmemmappedFile.txt", GENERIC_READ Or GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)
        
        fLen = GetFileSize(hFile, 0)
        
        hFileMap = CreateFileMapping(hFile, 0, PAGE_READWRITE, 0, 0, 0)
        
        hMM = MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0)
    
        Dim pFrom As Long
        pFrom = StrStr(hMM, byFrom(0))
        
        SetFilePointer hFile, pFrom - hMM, 0, FILE_BEGIN
        
        UnmapViewOfFile (hMM)
        CloseHandle hFileMap
        
        SetEndOfFile hFile
      
        CloseHandle hFile
    



  • di patel data: 29/09/2017 10:50:45

    scusami Antonio, potresti aggiungere qualche commento al codice ?
    credevo fosse facile ormai eliminare la prima parte del testo fino alla parola scelta, ma non ci riesco.





  • di oregon (utente non iscritto) data: 29/09/2017 13:14:43

    Certamente ... parli della prima versione o della seconda?

    Puoi mostrare anche cosa hai scritto tu per capire dove sbagli ...



  • di patel data: 29/09/2017 16:26:12

    io ho ottenuto il risultato di eliminare la prima parte del testo fino alla parola scelta utilizzando la prima versione e modificando la riga
    pFrom = StrStr(hMM, byFrom(0))
    in
    pFrom = hMM
    e quindi col codice sotto riportato
    ma credo si possa fare di meglio, tutti gli altri tentativi producono file mostruosi, quindi è chiaro che non ho capito i vari comandi, in particolare SetFilePointer e MoveMemory e non sono riuscito a trovare documentazione in merito.
    Invece di andare a caso preferirei capire.
     
        Dim byTo() As Byte
        Dim byToLen As Long
        byTo = StrConv("FRASE DA CERCARE" & Chr(0), vbFromUnicode)
        byToLen = UBound(byTo) ' 22
        sfile = "F:TEST.txt"
        dfile = "F:TEST_Ridotto.txt"
        FileCopy sfile, dfile
    
        Dim hFile As Long
        hFile = CreateFile(dfile, GENERIC_READ Or GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)
        
        Dim fLen As Long
        fLen = GetFileSize(hFile, 0)
        
        Dim hFileMap As Long
        hFileMap = CreateFileMapping(hFile, 0, PAGE_READWRITE, 0, 0, 0)
        
        Dim hMM As Long
        hMM = MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0)
        Dim pTo As Long
        pTo = StrStr(hMM, byTo(0))
        SetFilePointer hFile, pTo - hMM, 0, FILE_BEGIN
        Dim pLen As Long
        pLen = fLen + hMM - pTo
        MoveMemory hMM, pTo, pLen
        UnmapViewOfFile (hMM)
        CloseHandle hFileMap
        SetFilePointer hFile, fLen - (pTo - hMM), 0, FILE_BEGIN
        SetEndOfFile hFile
        CloseHandle hFile






  • di oregon (utente non iscritto) data: 29/09/2017 16:59:00

    E' corretto così come hai fatto. Perché non ti convince?



  • di patel data: 29/09/2017 17:05:49

    nel frattempo ho fatto qualche modifica al post precedente, non mi convince perché ne caso di eliminare la parte finale hai usato un codice molto più ridotto senza usare movememory e poi vorrei capire quello che faccio e non andare a tentativi





  • di oregon (utente non iscritto) data: 29/09/2017 18:25:40

    La MoveMemory è necessaria se vuoi conservare parti finali del file.

    Considera il problema equivalente a quello di un vettore di numeri

    1 2 3 4 5 6 7 8 9 0

    e analizza i vari casi:

    a) vuoi eliminare dal 4 (compreso) al 7 (non compreso) :
    ..a1) trovi la posizione del 4
    ..a2) trovi la posizione del 7
    ..a3) muovi gli elementi dal 7 a 0 a partire dalla posizione del 4
    ..a4) il vettore è diventato 1 2 3 7 8 9 0 8 9 0
    ..a5) tronchi il vettore dopo l'elemento 0
    ..a6) il vettore diventa 1 2 3 7 8 9 0

    b) vuoi eliminare dal 4 (compreso) alla fine
    ..b1) trovi la posizione del 4
    ..b2) tronchi il vettore dall'elemento 4 in poi
    ..b3) il vettore diventa 1 2 3

    c) vuoi eliminare dall'inizio all'elemento 7 (non compreso)
    ..c1) trovi la posizione del 7
    ..c2) muovi gli elementi dal 7 a 0 a partire dalla posizione 1
    ..c3) il vettore è diventato 7 8 9 0 5 6 7 8 9 0
    ..c4) tronchi il vettore dopo l'elemento 0
    ..c5) il vettore diventa 7 8 9 0



  • di patel data: 29/09/2017 19:06:40

    Grazie Antonio, non ci sarei mai arrivato, ora è tutto chiaro
    nel caso C perché non è possibile troncare il vettore dal 7 all'inizio ed evitare il movememory ?





  • di oregon (utente non iscritto) data: 30/09/2017 16:26:11

    Troncare un file significa cambiare il punto di fine. Non puoi modificare il punto di inizio.



  • di patel data: 30/09/2017 17:27:38

    allora a cosa serve la variabile FILE_END (2) ? ho cercato di documentarmi un po' senza molto successo





  • di oregon (utente non iscritto) data: 30/09/2017 20:38:36

    FILE_END non è una variabile ma una costante che è possibile usare come ultimo argomento
    della funzione SetFilePointer (quello denominato dwMoveMethod)

    La funzione SetFilePointer è una API che serve a impostare il puntatore interno di
    un file usato per successive operazioni (lettura/scrittura/troncamento).
    Il valore del puntatore passato come argomento alla funzione non è assoluto ma
    relativo al metodo passato come ultimo argomento. Ovvero

    0 FILE_BEGIN ... posizionamento relativo all'inizio del file
    1 FILE_CURRENT ... posizionamento relativo al valore attuale del puntatore
    2 FILE_END ... posizionamento relativo alla fine del file

    Quindi se, ad esempio, passi un valore eguale a 100 e FILE_BEGIN il puntatore
    viene posizionato al byte 100 a partire dall'inizio del file. Se passi -100 eguale
    FILE_END il puntatore passerà a 100 byte prima della fine del file.
    Con valori +n o -m e FILE_CURRENT il puntatore sarà spostato in avanti o indietro
    di n bytes.


    Per i dettagli

    SetFilePointer
    h t t p s://msdn.microsoft.com/en-us/library/windows/desktop/aa365541(v=vs.85).aspx



  • di patel data: 01/10/2017 10:25:07

    cit.
    Troncare un file significa cambiare il punto di fine. Non puoi modificare il punto di inizio.

    grazie Antonio, prendo atto di quanto hai detto, è stata una bella lezione, per me l'argomento è chiuso.





  • di Fabio (utente non iscritto) data: 02/10/2017 16:28:07

    scusa oregon se riprendo la discussione....
    sto utilizzando la tua macro (seconda soluzione) su dei file che avevo in precedenza ridotto parzialmente (in modo manuale) di 1.123.443 righe e funziona perfettamente.
    Ho voluto provare sul file originale di 3.227.092 righe ma mi elimina tutte le righe creando un file vuoto.
    Penso sia lo stesso problema che aveva segnalato Vecchio Frac dovuto alla dimensione del file.
    Ecco i valori che mi da la macro andando riga per riga (se può essere d'aiuto) :
    hFile=1340
    fLen=492385032
    hFileMap=1164
    hMM=0
    pForm=0
    Ho anche seguito i suggerimenti che hai dato a patel per vedere se mi potevano essere utili a risolvere il problema ma non sono stato in grado di comprenderli.
    Si può fare qualcosa?
    Grazie



  • di patel data: 02/10/2017 18:41:26

    io penso che se la posizione della stringa da cercare (pfrom) è = 0 non viene trovata la stringa, lo strano è hMM = 0
    ma sei sicuro che hMM = 0 ?






  • di oregon (utente non iscritto) data: 02/10/2017 20:01:59

    Quando è grande esattamente il file (in byte)?



  • di FABIO (utente non iscritto) data: 02/10/2017 20:05:43

    sono 480.845 byte
    ora verifico quello che mi hai chiesto



  • di oregon (utente non iscritto) data: 02/10/2017 20:09:05

    Vuoi dire 480.845 Kbyte non byte



  • di oregon (utente non iscritto) data: 02/10/2017 20:10:10

    Comunque, come prima, mi devi fare avere il file (zippato) e il codice sorgente (esatto) che usi.



  • di FABIO (utente non iscritto) data: 02/10/2017 20:10:26

    si scusa



  • di FABIO (utente non iscritto) data: 02/10/2017 20:13:24

    va ancora bene l'indirizzo email temporaneo che mi avevi dato?
    per "codice sorgente" intendi la macro che mi hai creato e che ho adattato?



  • di patel data: 02/10/2017 20:23:13

    cit. per "codice sorgente" intendi la macro che mi hai creato e che ho adattato?

    ESATTO





  • di oregon (utente non iscritto) data: 02/10/2017 20:24:27

    Va bene l'indirizzo.

    Sì ... la macro .. il codice VBA che non va (!)



  • di fabio (utente non iscritto) data: 02/10/2017 20:51:39

    facendo una verifica ho visto che nella stringa poteva esserci il solito "a capo" che dava fastidio.
    Ho cambiato la stringa (sempre sulla stessa riga) ma mi ha creato un file di 3.395.712 kb.
    Inserisco il codice che ho usato.
    Ti sto inviando il file sempre tramite wetranfert all'indirizzo che mi avevi dato
     
    Sub macro2()
     Dim hFile As Long
        Dim fLen As Long
        
        Dim byFrom() As Byte
        Dim byFromLen As Long
        byFrom = StrConv("IM_DRB_FISC_FIR" & Chr(0), vbFromUnicode)
        byFromLen = UBound(byFrom)
        
        hFile = CreateFile("D:AGEST178_TXTGP_0.txt", GENERIC_READ Or GENERIC_WRITE, 0, 0, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)
        
        fLen = GetFileSize(hFile, 0)
        
        hFileMap = CreateFileMapping(hFile, 0, PAGE_READWRITE, 0, 0, 0)
        
        hMM = MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0)
    
        Dim pFrom As Long
        pFrom = StrStr(hMM, byFrom(0))
        
        SetFilePointer hFile, pFrom - hMM, 0, FILE_BEGIN
        
        UnmapViewOfFile (hMM)
        CloseHandle hFileMap
        
        SetEndOfFile hFile
      
        CloseHandle hFile
    End Sub



  • di oregon (utente non iscritto) data: 02/10/2017 22:01:11

    Il problema sta nel fatto che nel file esistono dei valori binari con valore 00
    Il file non è un file di testo, ma un file binario.

    La API StrStr, usata per cercare la stringa iniziale, interrompe la ricerca appena trova il valore 00 nel file perché ritiene che la stringa sia terminata. Quindi il valore restituito è sempre 0 e tutto il resto non funziona.

    Una soluzione sarebbe quella di usare una API diversa da StrStr che cerchi una sequenza di byte all'interno di una sequenza di byte ma, sfortunatamente (strano a dirsi), non esiste in Windows una API simile (in realtà non esiste neanche nella libreria standard del C ma esiste qualcosa di simile in estensioni del C, la funzione memmem e in C++).

    La funzione memmem (quella che cerca byte in un buffer di byte) può essere riscritta.
    Ma in VBA sarebbe lentissima e quindi inutilizzabile.

    Quindi, due strade

    1) il file non può essere trattato con questo codice

    2) si riscrive la memmem in C e tutto il codice finisce adesso scritto in VBA finisce in una apposita DLL che può essere utilizzata da Excel





  • di patel data: 03/10/2017 09:34:48

    Io credo che una Dll del genere possa tornare utile a molti utenti, se hai tempo e voglia ....





  • di oregon (utente non iscritto) data: 03/10/2017 11:15:33

    Sicuramente il tempo è tiranno ... comunque vedrò di fare qualcosa nel we ...

    Magari una prima versione di DLL la posto sabato o domenica ...



  • di oregon (utente non iscritto) data: 03/10/2017 21:45:50

    Ho fatto un po' prima ... avevo un po' di tempo e ho scritto una prima versione.

    Andiamo per ordine.

    La DLL si chiama

    MMFile.dll

    ed è a 32 bit. E' scaricabile da questo indirizzo

    h t t p s://www.dropbox.com/s/sa8mufcziw2sfrf/MMFile.dll?dl=0&m=

    e per essere eseguita ha bisogno del runtime del Visual C++ 2015.
    Se avete un errore in cui vi viene evidenziata la mancanza del file VCRuntime140.dll
    (dovrebbe stare in C:WindowsSystem32) vuol dire che non avete installato questo
    runtime e lo dovete scaricare da MS

    Microsoft Visual C++ 2015 Redistributable Update 3 RC
    h t t p s://www.microsoft.com/en-US/download/details.aspx?id=52685

    nella versione a 32 bit e lingua (italiano/inglese) del vostro sistema.

    Per utilizzare la MMFile.dll basta copiarla in una cartella (a vostro piacimento) e dichiarare
    la funzione nel modulo di Excel con il codice

    Public Declare Function ReduceFile Lib "C:CartellaSceltaMMFile.dll" _
    (ByVal FileName As String, ByVal BlockStart As String, ByVal BlockStop As String) As Long

    La funzione ReduceFile è quella che deve essere utilizzata e che prevede 3 parametri

    - nome del file su cui operare
    - prima stringa da cercare
    - seconda stringa da cercare

    Il nome del file e la prima stringa sono obbligatori. Se la seconda stringa viene lasciata
    vuota la funzione opera in maniera differente. La funzione restituisce un valore long.
    L'uso (in VBA, ma può essere eseguita anche nelle formule) è il seguente

    Dim er As Long
    er = ReduceFile("C:CartellaFiledaridurre.txt", "IM_DRB_FISC_FIR", "")

    e in questo caso la stringa indicata verrà cercata. Da quella stringa in poi il file sarà troncato.

    Se si indica anche l'altra stringa, invece

    Dim er As Long
    er = ReduceFile("C:CartellaFiledaridurre.txt", "NXWEB_TITOLO", "NXWEB_SIN_INCR_PRT")

    il blocco compreso tra le stringhe sarà eliminato e il file ridotto.

    Il valore long restituito, in caso di funzionamento corretto sarà eguale a

    0 (nessun errore)

    In caso contrario sarà indicato un valore negativo con i seguenti errori

    -1 Nome file non indicato
    -2 Prima stringa non indicata
    -3 Errore durante la CreateFile
    -4 File troppo grande
    -5 Errore durante la CreateFileMapping
    -6 Errore durante la MapViewOfFile
    -7 Errore di allocazione di memoria
    -8 Prima stringa non trovata
    -9 Seconda stringa non trovata

    Spero di essere stato chiaro e che non ci siano (tanti) bug. Fatemi sapere.



  • di patel data: 04/10/2017 08:34:51

    ho provato con un file di testo con la seguente macro, ma ottengo -3 come risultato.
    La runtime ce l'ho.
    Con le stesse parole la vecchia macro funziona perfettamente 
    Allego file Livorno.txt
     
    Public Declare Function ReduceFile Lib "F:DocumentiExcelfileMacro-VBAMMFile.dll" _
    (ByVal FileName As String, ByVal BlockStart As String, ByVal BlockStop As String) As Long
    
    Sub elimina_righe() ' da parola a parola
    Dim er As Long, sfile As String, dfile As String
    sfile = "F:DocumentiExcelfileMacro-VBALivorno.txt"
    dfile = "F:downloadLivornoRidotto.txt"
    FileCopy sfile, dfile
    er = ReduceFile(dfile, "ACQUARIO COMUNALE", "LA CUCINA LIVORNESE")
    'er = ReduceFile(dfile, "ACQUARIO COMUNALE", "")
    
    End Sub






  • di oregon (utente non iscritto) data: 04/10/2017 09:25:00

    E' possibile che quando parte la funzione, il sistema non abbia rilasciato il file di destinazione a seguito della FileCopy.

    Per capire se è questo, prova ad operare sul file copiato senza fare la FileCopy.



  • di patel data: 04/10/2017 14:34:58

    provato, stesso risultato.





  • di oregon (utente non iscritto) data: 04/10/2017 15:49:03

    Sicuro che il file è accessibile (non readonly, nessuna autorizzazione particolare richiesta...)?

    Il problema è su altri file i solo su questo?

    Puoi farmelo scaricare?

    P.S. Sembra un problema "a monte" ... Non si riesce ad aprire il file ...



  • di patel data: 04/10/2017 18:12:44

    l'avevo già allegato, lo trovi accanto al pulsante Nuova Risposta all'inizio della discussione, si chiama Livorno.txt
    provato con altri file di testo, sempre -3





  • di oregon (utente non iscritto) data: 04/10/2017 19:35:43

    A me ha funzionato correttamente.

    Scarica la nuova versione della DLL da

    h t t p s://www.dropbox.com/s/er6lcqs765rm7lh/MMFile.dll?dl=0&m=

    in cui la CreateFile restituisce un codice d'errore di dettaglio per capire cosa ti succede.



  • di patel data: 04/10/2017 20:07:55

    ora mi dà er = 2, ma il file non viene modificato





  • di oregon (utente non iscritto) data: 04/10/2017 22:08:21

    La questione è che VBA passa gli argomenti stringa in maniera diversa da come succede quando si usa la funzione in una cella del foglio.

    Allora ho modificato il codice per renderlo compatibile SOLO con il VBA e non con le formule.

    La nuova DLL è scaricabile da

    h t t p s://www.dropbox.com/s/fvagd4xf3n537gp/MMFile.dll?dl=0&m=

    e la lista degli errori è adesso la seguente

    -1 Nome file non indicato
    -2 Prima stringa non indicata
    -3 Errore durante la CreateFile
    -4 File troppo grande
    -5 Errore durante la CreateFileMapping
    -6 Errore durante la MapViewOfFile
    -7 Prima stringa non trovata
    -8 Seconda stringa non trovata



  • di patel data: 05/10/2017 06:58:51

    perfetto





  • di oregon (utente non iscritto) data: 05/10/2017 17:38:47

    Sarebbe bene che lo provasse Fabio a cui serviva la ricerca in un file binario



  • di patel data: 05/10/2017 19:34:42

    giusto, ma intanto una scremata è stata fatta





  • di fabio (utente non iscritto) data: 05/10/2017 19:57:42

    oggi non ho avuto molto tempo ma ho fatto una prova veloce.
    con il file txt che avevo ridotto manualmente (circa 1.200.000 righe) ha funzionato perfettamente, mentre con il file non ridotto (più di 3.000.000 di righe) non ha eliminato nessuna riga senza darmi nessun errore (il file ha mantenuto la stessa data e ora di creazione).
    in entrabe le prove ho usato le stesse stringhe che si trovano all'inizio del file.
    Se riesco domani faccio ulteriori prove



  • di patel data: 06/10/2017 08:58:09

    attenzione, l'errore devi essere tu a ricavartelo aggiungendo una riga del tipo
    msgbox(er)
    io per conoscerlo lanciavo la macro con F8 step by step






  • di fabio (utente non iscritto) data: 06/10/2017 10:28:33

    mi da errore -6



  • di oregon (utente non iscritto) data: 06/10/2017 13:16:53

    Stai usando l'ultima versione di dll, giusto?

    Il file è quello che ho già scaricato? Cosa cerchi?
    Mostra il codice vba che hai usato.




  • di fabio (utente non iscritto) data: 06/10/2017 14:09:34

    si, l'ultima che hai creato.
    il codice che ho usato per delle prove ricerca poche righe da eliminare e che si trovano all'inizio del file (dalla riga 141 alla 154)
    in effetti a me servirebbe eliminare tutte le righe dalla stringa "NXWEB_TITOLO_DETT" (riga 1.123.444) alla fime del file
    Ti confermo che il file che ho utilizzato è il secondo (quello grande) che ti ho inviato
     
    Public Declare Function ReduceFile Lib "D:AGESTRIDUCI_FILE_TXTDllMMFile.dll" _
    (ByVal FileName As String, ByVal BlockStart As String, ByVal BlockStop As String) As Long
    
    Sub elimina_righe() ' da parola a parola
    Dim er As Long, sfile As String, dfile As String
    sfile = "D:AGESTGP_01.txt"
    dfile = "D:AGESTGP_01_ridotto.txt"
    FileCopy sfile, dfile
    er = ReduceFile(dfile, "NXWEB_FORZA_VENDITA", "NXWEB_PVEND_COMP_ZONAINC")
    MsgBox (er)
    End Sub
    



  • di patel data: 06/10/2017 18:14:30

    se ben ricordi oregon aveva detto di evitare il FileCopy specialmente col tuo file (penso qualche giga).
    prova così 
     
    Public Declare Function ReduceFile Lib "D:AGESTRIDUCI_FILE_TXTDllMMFile.dll" _
    (ByVal FileName As String, ByVal BlockStart As String, ByVal BlockStop As String) As Long
    
    Sub elimina_righe() ' da parola a parola
    Dim er As Long, sfile As String, dfile As String
    sfile = "D:AGESTGP_01.txt"
    er = ReduceFile(sfile, "NXWEB_FORZA_VENDITA", "NXWEB_PVEND_COMP_ZONAINC")
    MsgBox (er)
    End Sub






  • di Fabio (utente non iscritto) data: 06/10/2017 19:22:45

    ho provato anche senza fare la copia ma il problema rimane



  • di oregon (utente non iscritto) data: 06/10/2017 21:37:52

    Ok Fabio, ho provato e a me ha funzionato senza problemi con il tuo file.

    Comunque, ho modificato la DLL per farmi restituire un codice d'errore più dettagliato (un valore positivo). Prova a scaricare e usare questa

    h t t p s://www.dropbox.com/s/tn1q7oyor0cx5hg/MMFile.dll?dl=0&m=

    e dimmi il valore restituito.



  • di fabio (utente non iscritto) data: 06/10/2017 22:24:57

    ho provato con il pc di casa ed ha funzionato perfettamente (er 0) sia con l'eliminazione da stringa a stringa che da stringa a fine file.
    Lunedì farò un'altra prova con pc in ufficio per la conferma definitiva.
    Per ora grazie infinite anche a patel.
    Buon we



  • di fabio (utente non iscritto) data: 09/10/2017 16:33:14

    Ok anche con il pc in ufficio (molto efficace e veloce).
    Grazie mille e ancora complimenti per le vostre competenze e la vostra tenacia.
    Buona settimana.



  • di patel data: 09/10/2017 17:01:00

    Grazie a te del riscontro e di aver proposto un quesito decisamente interessante, tanto da attirare un esperto del calibro di Antonio Giuliana





  • di oregon (utente non iscritto) data: 09/10/2017 20:05:54

    Mi fa piacere che hai risolto Fabio, anche se non ho capito quale fosse l'ultimo problema che si era presentato prima del we.

    Comunque, se tutto è risolto meglio così.

    @patel ... troppo buono ... sai che non sono d'accordo sul fornire la "pappa pronta" ma questo era un caso molto particolare, non si poteva fare diversamente.

    P.S. Esiste un mio omonimo informatico di Napoli ... non sono io ...