IALweb Homepage
Forum Home Forum Home > MS Office > Microsoft Office > Microsoft Access
  New Posts New Posts RSS Feed - [RISOLTO]Dimensione file del link su txtbox
  FAQ FAQ  Forum Search   Events   Register Register  Login Login


REGISTRATEVI su IALWeb forum!

[RISOLTO]Dimensione file del link su txtbox

 Post Reply Post Reply Page  12>
Author
Message
surfgarden View Drop Down
Utente Base
Utente Base


Joined: 08/Dic/2016
Location: Vicenza
Status: Offline
Points: 85
Post Options Post Options   Thanks (0) Thanks(0)   Quote surfgarden Quote  Post ReplyReply Direct Link To This Post Topic: [RISOLTO]Dimensione file del link su txtbox
    Posted: 29/Dic/2017 at 09:53
Salve a tutti.
In una sottomaschera (continua) è presente una txtbox (txtFileLink) in cui inserisco percorso e nome del file descritto nel record corrente.
L'inserimento lo eseguo mediante fDialog (msoFiledialogFilePicker)
Volevo sapere se vi è modo di far rilevare ad Access la dimensione del file dal link presente nella txtFileLink, ed inserirlo in altra casella di testo (txtDimGB).
In altri termini... txtDimGB = "..dimensione del file corrispondente al link presente su txtFileLink.."
Grazie per ogni aiuto


Edited by surfgarden - 02/Gen/2018 at 01:24
Back to Top
Sponsored Links


Back to Top
@Alex View Drop Down
Utente Onorario
Utente Onorario
Avatar

Joined: 09/Apr/2012
Location: Mantova
Status: Offline
Points: 4978
Post Options Post Options   Thanks (0) Thanks(0)   Quote @Alex Quote  Post ReplyReply Direct Link To This Post Posted: 29/Dic/2017 at 10:50
Function FileLen(PathName As String) As Long
    Membro di VBA.FileSystem

http://https://msdn.microsoft.com/en-us/VBA/Language-Reference-VBA/articles/filelen-function
quindi:
http://https://www.techonthenet.com/access/functions/file/filelen.php
tu dovrai sostituire il percorso Fisso con il Campo Path...
Se poi vuoi il valore in MB, dividi per 1024...
Format((FileLen(CampoPath) / 1024 / 1024), "000") & " MB"


Potresti scrivere una Funzione alla quale passi il Path e restituisce la stringa formattata in base al Size, Kb/Mb o Gb...
Function GetSize(FilePath as String) As String

On Error GoTo hell
Dim lngSize As Long
lngSize=FileLen(FilePath)
If lngSize>= 1073741824 Then
    GetSize= Format(lngSize/ 1024 / 1024 / 1024, "#0.00") & " GB"
ElseIf Bytes >= 1048576 Then
    GetSize= Format(lngSize/ 1024 / 1024, "#0.00") & " MB"
ElseIf Bytes >= 1024 Then
    GetSize= Format(lngSize/ 1024, "#0.00") & " KB"
ElseIf Bytes < 1024 Then
    GetSize= Fix(lngSize) & " Bytes"
End If

Exit Function
hell:
GetSize = "0 Bytes"
End Function

Non SUPPORTO il CROSSPOST.
Mio Sito
Scaricare i DEMO modificando l'Estensione.
Back to Top
surfgarden View Drop Down
Utente Base
Utente Base


Joined: 08/Dic/2016
Location: Vicenza
Status: Offline
Points: 85
Post Options Post Options   Thanks (0) Thanks(0)   Quote surfgarden Quote  Post ReplyReply Direct Link To This Post Posted: 29/Dic/2017 at 11:34
Ciao Alex.
I tuoi link mi venivano bloccati da Viglink come URL invalidi Ouch
..riprovando ora mi danno "immpossibile raggiungere il sito" e rinviano alla generica webpage

Intanto..ottima la funzione per modificare in GB/Mb/Kb


EDIT: cmq ho messo a fuoco la funzione FileLen come punto di orientamento, e sto trovando informazioni sul web.
Dovrei riuscirci...al che segnalerò il [RISOLTO]
Grazie mille Alex



Edited by surfgarden - 29/Dic/2017 at 11:55
Back to Top
@Alex View Drop Down
Utente Onorario
Utente Onorario
Avatar

Joined: 09/Apr/2012
Location: Mantova
Status: Offline
Points: 4978
Post Options Post Options   Thanks (0) Thanks(0)   Quote @Alex Quote  Post ReplyReply Direct Link To This Post Posted: 29/Dic/2017 at 12:53
La funzione fa già tutto ti basta richiamarla nella query per generare un campo calcolato che poi associ alla textbox.
Non SUPPORTO il CROSSPOST.
Mio Sito
Scaricare i DEMO modificando l'Estensione.
Back to Top
surfgarden View Drop Down
Utente Base
Utente Base


Joined: 08/Dic/2016
Location: Vicenza
Status: Offline
Points: 85
Post Options Post Options   Thanks (0) Thanks(0)   Quote surfgarden Quote  Post ReplyReply Direct Link To This Post Posted: 29/Dic/2017 at 15:04

EDIT: ...Tutti i file superiori a 2 GB vengono ridotti o saltati o restituiti in " 0 Bytes"!
es. 1,47 GB  lo scrive correttamente
5,56 lo riduce a 1,56; 11,90 lo riduce a 1,90; ecc...

E' un limite di Access? 

EDIT 2: ..quanto sopra non lo fa con tutti i file superiori a 2Gb: Bensì solo con  i file da 5, 9, 11, 13  GB

EDIT 3: ..riverifico esattamente tutto il comportamento..poi posto i risultati con maggior correttezza.

Scusami per le correzioni continue qui sopra..



Edited by surfgarden - 30/Dic/2017 at 12:56
Back to Top
surfgarden View Drop Down
Utente Base
Utente Base


Joined: 08/Dic/2016
Location: Vicenza
Status: Offline
Points: 85
Post Options Post Options   Thanks (0) Thanks(0)   Quote surfgarden Quote  Post ReplyReply Direct Link To This Post Posted: 30/Dic/2017 at 16:56
Ho provato anche installando la versione valutativa di Office 365.
La funzione (leggermente modificata..spero opportunamente) restitusce correttmente solo i file inferori ai 2Gb.
Quelli superiori si comportano in modo completamente sballato.

A scanso di equivoci, riporto il modulo (in rosso dove modidicato) e l'SQL della query

Public Function fExtension(strFile As String) As String
   Dim intPointPos As Integer
   If Len(strFile) = 0 Then Exit Function
   intPointPos = InStrRev(strFile, ".")
   If intPointPos = 0 Then Exit Function
   fExtension = Mid$(strFile, intPointPos + 1, Len(strFile))
End Function

Function GetSize(FilePath As String) As String
On Error GoTo hell
Dim lngSize As Long

lngSize = FileLen(FilePath)
If lngSize >= 1073741824 Then
    GetSize = Format(lngSize / 1024 / 1024 / 1024, "#0.00") & " GB"
ElseIf lngSize >= 1048576 Then
   GetSize = Format(lngSize / 1024 / 1024, "#0.00") & " MB"
ElseIf lngSize >= 1024 Then
   GetSize = Format(lngSize / 1024, "#0.00") & " KB"
ElseIf lngSize < 1024 Then
   GetSize = Fix(lngSize) & " Bytes"
End If

Exit Function
hell:
GetSize = "0 Bytes"
End Function

La query (dove il campo [Dimensione GB] è quello in cui avevo riportato la dimensione manualmente) è la seguente:

SELECT PERCORSI.IDfilm, PERCORSI.Nome, PERCORSI.[Percorso e nome], PERCORSI.[Dimensione GB], GetSize([PERCORSI]![Percorso e nome]) AS DimGB, fExtension([PERCORSI]![Percorso e nome]) AS Ext
FROM PERCORSI;

e questo un esempio di cosa restituisce la query (relativamente ai campi Dimensione GB e DimGB
Dimensione GB	DimGB
18,23........ 0 Bytes
17,38........ 0 Bytes
15,9........ 0 Bytes
15,36........ -686780418 Bytes
14,4........ -1662024603 Bytes
13,38........ 0 Bytes
13,03........ 1,03 GB
12,88........ 897,91 MB
12,47........ 484,41 MB
12,46........ 0 Bytes
12,34........ 343,87 MB
11,72........ -298292902 Bytes
11,7........ -296670440 Bytes
11,7........ 0 Bytes
11,6........ -346377008 Bytes
11,5........ -504709296 Bytes
11,48........ -560959312 Bytes
11,47........ -568764406 Bytes
11,47........ 0 Bytes
11,46........ -583687475 Bytes
11,46........ -581415361 Bytes
11,46........ 0 Bytes
11,45........ -590503924 Bytes
11,45........ 0 Bytes
11,43........ -614092146 Bytes
11,29........ 0 Bytes
11,22........ -841248336 Bytes
9,38........ 1,39 GB
9,38........ 0 Bytes
9,37........ 1,38 GB
9,23........ 1,23 GB
2........ -2145532236 Bytes
2........ 2,00 GB
2........ 2,00 GB
1,99 ........1,99 GB
1,99........ 1,99 GB
1,99........ 0 Bytes
1,98........ 1,98 GB
1,97........ 1,97 GB
1,97........ 1,97 GB
1,97........ 0 Bytes
1,97........ 0 Bytes
1,97........ 0 Bytes
1,96........ 1,96 GB
1,96........ 0 Bytes
1,95 ........1,95 GB
1,95........ 1,95 GB
1,95........ 1,95 GB
1,95........ 1,95 GB

Non capisco proprio questo comportamento anomalo..



Edited by surfgarden - 30/Dic/2017 at 17:10
Back to Top
willy55 View Drop Down
Moderatore
Moderatore
Avatar
Esperto di Access

Joined: 03/Ago/2011
Location: Italy
Status: Offline
Points: 9523
Post Options Post Options   Thanks (0) Thanks(0)   Quote willy55 Quote  Post ReplyReply Direct Link To This Post Posted: 30/Dic/2017 at 18:26
Willy
Back to Top
@Alex View Drop Down
Utente Onorario
Utente Onorario
Avatar

Joined: 09/Apr/2012
Location: Mantova
Status: Offline
Points: 4978
Post Options Post Options   Thanks (0) Thanks(0)   Quote @Alex Quote  Post ReplyReply Direct Link To This Post Posted: 31/Dic/2017 at 16:23
Originally posted by willy55 willy55 wrote:

Leggi seguenti discussioni che trattano (e risolvono) il limite nella determinazione corretta dei file con dimensione che superino i 2 GB:

 


Ottimo Willy, per l'uso che ne deve fare, userei il 3° Link e nello specifico la funzione
ULongToCurrency


Credo lascerei perdere Librerie esterne o API solo per come queste intergiscono con l'esecuzione, ed in Queries di questo tipo penso potrebbero rallentarne molto l'esecuzione.
Istanziare in LateBinding FSO è sicuramente lentissimo e se non ONESHOT direi che darebbe da fare...
La chiamata API, credo che pur se l'apertura di un Binary, come fa quella chiamata, è molto veloce... il codice è più macchinoso e da testare in relazione alla velocità... e se qualche cosa si pianta ho il sospetto blocchi il file fino alla chiusura di Access....

La funzione nativa è più ErrorFree e con la modifica indicata dal 3° Link la reputo più snella e sicura.
Non SUPPORTO il CROSSPOST.
Mio Sito
Scaricare i DEMO modificando l'Estensione.
Back to Top
surfgarden View Drop Down
Utente Base
Utente Base


Joined: 08/Dic/2016
Location: Vicenza
Status: Offline
Points: 85
Post Options Post Options   Thanks (0) Thanks(0)   Quote surfgarden Quote  Post ReplyReply Direct Link To This Post Posted: 01/Gen/2018 at 14:41
Grazie a Willy e Alex per gli interventi
Intanto.. Buon Anno Nuovo a voi e a tutto il forum

Avevo già trovato il primo link di Willy, e pensavo proprio di partire da lì. Gli altri visualizzavano codici VB e non VBA, e mi lasciavano erroneamente perplesso
Questa mattina ho fatto diverse prove, partendo dal suggerimento di Alex. Ho quindi provato a modificare il modulo nel modo seguente
Function GetSize(FilePath As String) As String
On Error GoTo hell
GetSize = FileLen(FilePath)
Exit Function
hell:
GetSize = "0 Bytes"
End Function

Public Function ULongToCurrency(ByVal Value As Long) As Currency
    If Value < 0 Then
        ULongToCurrency = CCur(Value And &H7FFFFFFF) + 2147483648#
    Else
        ULongToCurrency = CCur(Value)
    End If
End Function

La query diviene
SELECT PERCORSI.[Percorso e nome], PERCORSI.[Dimensione GB], PERCORSI.[Dimensione MB], GetSize([PERCORSI]![Percorso e nome]) AS Dimm
FROM PERCORSI;
dove [Dimensione GB] e [Dimensione MB] sono inseriti in tabella manualmente (...o meglio..attraverso sw di DyrectoryList esportato in Excel)

e in maschera richiamo la funzione su txtbox:

Private Sub Form_Current()
    Me.txtDimFile.Value = ULongToCurrency(FileLen([txtPercorso_e_nome]))
End Sub

Risultato: abbiamo fatto un gradino in più: ora mi restituisce correttamente i file fino a 4 GB ..dopodiché sballa di nuovo (pur restituendomi solo valori positivi).

Spero di aver capito anche l'altra problematica esposta da Alex (spero di non scrivere enormi stupidaggini!): utilizzare FileSistemObject costringe ogni apertura del db di Access ad interrogare  Windows sulle proprietà di ogni singolo file per rilevarne la dimensione, il che, a fronte di circa 3000 file (destinati ad aumentare) causerebbe rallentamenti d'esecuzione inaccettabili.
Questo credo il punto di partenza
Private Sub ShowFileInfo(filespec)
    Dim fs, f, s
    Set fs = CreateObject("Scripting.FileSystemObject")
    Set f = fs.GetFile(filespec)
    s = f.Size
End Sub

Forse la soluzione migliore sarebbe l'inserimento  della dimensione del file  in un campo della tabella PERCORSI contestualmente all'inserimento del percorso stesso, ma non sono in grado di aggiungere quanto occorre al codice:
Private Sub cmdSfoglia_Click()

   Dim fDialog As Office.FileDialog
   Dim varFile As Variant
   Dim Filters As String
   Dim FileName As String
   
   Me.FileList.RowSource = ""
   Set fDialog = Application.FileDialog(msoFileDialogFilePicker)
   With fDialog
         .AllowMultiSelect = False
      .Title = "Seleziona percorso file del Film:"
      .Filters.Clear
       Filters.Add "Mkv", "*.MKV"
      .Filters.Add "DivX, Xvid,", "*.AVI"
      .Filters.Add "Tutti i file", "*.*"
 
      If .Show = True Then
        For Each varFile In .SelectedItems
            Me.FileList.AddItem varFile
        Next

       Else
         MsgBox "Hai cliccato Cancella nella finestra di dialogo"
      End If
   End With
End Sub

Se potete aiutarmi in quest'ultimo intento.. on line non sono riuscito a trovare niente in merito.
Grazie e ..ancora tanti a auguri di un sereno e prospero Beer2018





Edited by surfgarden - 01/Gen/2018 at 15:34
Back to Top
willy55 View Drop Down
Moderatore
Moderatore
Avatar
Esperto di Access

Joined: 03/Ago/2011
Location: Italy
Status: Offline
Points: 9523
Post Options Post Options   Thanks (0) Thanks(0)   Quote willy55 Quote  Post ReplyReply Direct Link To This Post Posted: 01/Gen/2018 at 17:12

Effettivamente la funzione ULongToCurrency permette di risolvere le dimensioni con file nell'intervallo compreso fra 2 e 4 GB, in quanto la funzione FileLen (utilizza un Long, e quindi 32 bit di cui uno per il segno) restituisce un valore negativo, il quale aggiunto alla base di partenza (quale limite ai 2 ^ 31 bit  = 2147483648 dei bit senza segno) permette di ottenere la corretta size del file.
Infatti se si prende un file di 3,94 GB (4.238.475.264 byte) la funzione FileLen restituisce -56492032 che trattato con la funzione  ULongToCurrency effettua la corretta conversione nel valore 4238475264
Il limite all'impiego della funzione FileLen e quindi anche a ULongToCurrency è che proprio la prima, agendo su un tipo Long, rappresenta un massimo di 2 ^ 32 bit quindi il valore fra 0 e 4294967295 (come massimo).

Sfortunatamente se si prendono dei file che superano i 4 GB non è possibile sfruttare le funzioni sopra-citate.
Infatti se si prende un file di 8,38 GB (9.001.203.689 byte) la funzione FileLen restituisce il valore 411269097 che seppure trattato dalla ULongToCurrency non da il valore corretto.
Allo stesso modo un file di 6,58 GB (7.076.188.160 byte) restituisce -1513746432 (come FileLen) che trattato, diventa: 2781220864, del tutto errato, in quanto dovrebbe essere legato al numero di bit in base al gruppo di 2 GB in cui ricade aumentando la base a cui far riferimento.
Se volessimo visualizzare l'andamento dei valori restituiti dalla FileLen, negli intervalli li potremmo rappresentare in:

GB:           0        2        4        6        8        10        12 GB
valori:        positivi negativi positivi negativi positivi  negativi
intervallo:          primo            secondo             terzo
 

Ne consegue che la funzione FileLen (operando in Long su 32 bit) restituisce un intervallo (fra positivi e negativi) al massimo di 4 GB e sarebbe necessario di ulteriori bit per individuare su quale intervallo stia operando.
Avendo tale informazione sarebbe possibile stabilire una funzione di calcolo con:

   valore forninto da FileLen + 2 ^ ( 31 + intervallo)
 
Pertanto riprendendo l'esempio precedente ove si abbia un file con lunghezza del file di 7076188160  la funzione FileLen restituisce un valore negativo come -1513746432 che ricade nel secondo intervallo per cui i valori corretti verrebbero pari a:

-1513746432 + 2 ^ (31 + 2)  = -1513746432 + 2 ^ 33 = -1513746432 + 8589934592 = 7076188160
corrisondenti a:
' 6,59021377563477 GB
' 6748,37890625     MB
' 6910340             KB
' 7076188160       byte


Ora non essendo disponibile tale opportunità vi è necessità di impiegare sistemi alternativi che dovranno essere valutati in base ai vincoli e limiti del progetto e ambiente impiegato.

Una strada può essere l'impiego delle API.

Un esempio è il seguente:


Option Compare Database
Option Explicit

' ======================================================================================
' Esempio di impiego delle API a 32 bit per determinare la dimensioni del file
' anche quando questo superi la size di 2 GB.
' Tratto da:
' http://newsgroups.derkeiler.com/Archive/Comp/comp.lang.basic.visual.misc/2009-12/msg00014.html
' https://groups.google.com/forum/#!topic/comp.lang.basic.visual.misc/hKlXpTEHYTE
' ======================================================================================

Private Declare Function CreateFile Lib "kernel32" _
    Alias "CreateFileA" (ByVal lpFileName As String, _
    ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, _
    lpSecurityAttributes As Any, _
    ByVal dwCreationDisposition As Long, _
    ByVal dwFlagsAndAttributes As Long, _
    ByVal hTemplateFile As Long) As Long
Private Declare Function GetFileSizeEx Lib "kernel32" _
    (ByVal hFile As Long, lpFileSize As Currency) As Boolean
Private Declare Function CloseHandle Lib "kernel32" _
    (ByVal hObject As Long) As Long
Private Const GENERIC_READ As Long = &H80000000
Private Const FILE_SHARE_READ As Long = &H1
Private Const OPEN_EXISTING As Long = 3
Private Const INVALID_HANDLE_VALUE As Long = -1

Private Function FileLength(s1 As String) As Currency
Dim hFile As Long, FileSize As Currency
hFile = CreateFile(s1, _
    GENERIC_READ, FILE_SHARE_READ, ByVal 0&, _
    OPEN_EXISTING, ByVal 0&, ByVal 0&)
If hFile <> INVALID_HANDLE_VALUE Then
    GetFileSizeEx hFile, FileLength
    CloseHandle hFile
    FileLength = FileLength * 10000@
Else
    FileLength = -1
End If
End Function


Public Function TestFileLenght(nomefile As String) As Double
' Funzione di prova della lunghezza del file tramite API 32 bit
' Esempio uso:
' ? TestFileLenght("C:\MioFile.TXT")
' ? TestFileLenght("C:\BigFile.ZIP")
' Debug.Print FileLength(nomefile)
TestFileLenght = FileLength(nomefile)

End Function


Altra soluzione è l'impiego dell'oggetto FSO (File System Object) con il quale è possibile avere informazioni o manipolare i file nelle applicazioni di Scripting.


Un esempio è il seguente:


' ======================================================================================
' La funzione impiega lo Scripting di FSO (File System Object in modo da ottenere
' la dimensione (size) del file tramite il sistema operativo.
' In tal modo non si utilizza la funzione FileLen che fornisce dati non congrui
' qualora si superi l'ampiezza dei 2 GB (4 byte restituiti dal tipo Long).
' Tratto da:
' https://access-programmers.co.uk/forums/showthread.php?t=155611
' https://social.msdn.microsoft.com/Forums/office/en-US/b8014bd8-3faa-4be9-8ba7-36abef9f4481/what-can-i-use-in-place-of-filelen-to-get-the-size-of-a-file?forum=accessdev
' http://www.visual-basic.it/Forum/tabid/151/aft/7153/Default.aspx#.Wkjw9NThBkg' Esempio uso:
' Uso:
' Debug.Print GetFileSizeWithScript("E:\BigFile.ZIP")
' restituisce la corretta dimensione anche per file che superino i 2GB.
' Ad esempio con un file di 7076188160 restituisce il corretto valore
' corrispondente a circa 7 GB ovvero 6.910.340 KB)
' ======================================================================================
Function GetFileSizeWithScript(nomefile As String) As Double
    Set FileObject = CreateObject("Scripting.FileSystemObject")
    Set File = FileObject.GetFile(nomefile)
    GetFileSizeWithScript = File.size   ' Dimensione del file restituito tramite size script del file system
    Set FileObject = Nothing
    Set File = Nothing
End Function

Concludendo, qualora si abbia necessità di gestire file con dimensioni superiori a 4 GB solo le due ultime funzioni sono in grado di assicurare la corretta size dei file.
Dal momento che le API sono strettamente legate al sistema operativo (con vincoli sui 32 o 64 bit) consiglio di valutare gli effettivi tempi e,  se accettabili, optare per l'ultima funzione (che impiega l'oggetto FSO) che vede il sistema operativo proprio come oggetto e, quindi, seppure più lento rispetto alle API, assicura una maggiore versatilità nell’ambiente impiegato.

 

 



Edited by willy55 - 01/Gen/2018 at 17:25
Willy
Back to Top
 Post Reply Post Reply Page  12>
  Share Topic   

Forum Jump Forum Permissions View Drop Down

Forum Software by Web Wiz Forums® version 10.17
Copyright ©2001-2013 Web Wiz Ltd.

This page was generated in 0,094 seconds.