2010-12-02 51 views
1

Fondamentalement, j'essaie d'utiliser un module ou des fonctions publiques pour tirer un datediff qui est seulement pour les jours ouvrables. Tout fonctionne en ce qui concerne le code, mais pour une raison quelconque avec un champ de date particulier (que j'ai ajouté après que la base de données a été en production depuis un certain temps) le code ne fonctionne pas correctement et je reçois le "Type de données Incompatibilité dans l'expression ". Je suis sûr à 99% que c'est un problème de données. Si je compare deux dates différentes, j'ai créé une table de test avec 10 enregistrements et elle fonctionne.Nécessité d'autoriser les valeurs Null ou "" pour Dates - Type de données de requête d'accès incompatibilité

Le champ est défini sur Date/Heure. Je suppose que ma question est, est-il de toute façon de se débarrasser des "" ou de faire en sorte que le code accepte ces blancs comme des nulls? ou les convertir?

C'est là que j'appelle la fonction dans la requête:

exp1: BusinessDays ([IntCallDate], [aIntCall1])

Et voici le code dans le module ...

Merci pour toute aide - BEAUCOUP apprécié!

Public Function BusinessDays(dteStartDate As Date, dteEndDate As Date) As Long 
On Error GoTo err_workingDays 
    Dim lngYear As Long 
    Dim lngEYear As Long 
    Dim dteStart As Date, dteEnd As Date 
    Dim dteCurr As Date 
    Dim lngDay As Long 
    Dim lngDiff As Long 
    Dim lngACount As Long 
    Dim dteLoop As Variant 
    Dim blnHol As Boolean 
    Dim dteHoliday() As Date 
    Dim lngCount As Long, lngTotal As Long 
    Dim lngThanks As Long 
    If IsDate(dteStartDate) And IsDate(dteEndDate) Then 'added here begin 
    dteStart = dteStartDate 
    dteEnd = dteEndDate 

    lngYear = DatePart("yyyy", dteStart) 
    lngEYear = DatePart("yyyy", dteEnd) 

    If lngYear <> lngEYear Then 
     lngDiff = (((lngEYear - lngYear) + 1) * 7) - 1 
     ReDim dteHoliday(lngDiff) 
    Else 
     ReDim dteHoliday(6) 
    End If 

    lngACount = -1 

    For lngCount = lngYear To lngEYear 
     lngACount = lngACount + 1 
     'July Fourth 
     dteHoliday(lngACount) = DateSerial(lngCount, 7, 4) 

     lngACount = lngACount + 1 
     'Christmas 
     dteHoliday(lngACount) = DateSerial(lngCount, 12, 25) 

     lngACount = lngACount + 1 
     'New Years 
     dteHoliday(lngACount) = DateSerial(lngCount, 1, 1) 

     lngACount = lngACount + 1 
     'Thanksgiving - 4th Thursday of November 
     lngDay = 1 
     lngThanks = 0 
     Do 
      If Weekday(DateSerial(lngCount, 11, lngDay)) = 5 Then 
       lngThanks = lngThanks + 1 
      End If 
      lngDay = lngDay + 1 
     Loop Until lngThanks = 4 

     dteHoliday(lngACount) = DateSerial(lngCount, 11, lngDay) 

     lngACount = lngACount + 1 
     'Memorial Day - Last Monday of May 
     lngDay = 31 
     Do 
      If Weekday(DateSerial(lngCount, 5, lngDay)) = 2 Then 
       dteHoliday(lngACount) = DateSerial(lngCount, 5, lngDay) 
      Else 
       lngDay = lngDay - 1 
      End If 
     Loop Until dteHoliday(lngACount) >= DateSerial(lngCount, 5, 1) 

     lngACount = lngACount + 1 
     'Labor Day - First Monday of Septemeber 
     lngDay = 1 
     Do 
      If Weekday(DateSerial(lngCount, 9, lngDay)) = 2 Then 
       dteHoliday(lngACount) = DateSerial(lngCount, 9, lngDay) 
      Else 
       lngDay = lngDay + 1 
      End If 
     Loop Until dteHoliday(lngACount) >= DateSerial(lngCount, 9, 1) 
     'MsgBox dteHoliday(5) 

     lngACount = lngACount + 1 
     'Easter 
     lngDay = (((255 - 11 * (lngCount Mod 19)) - 21) Mod 30) + 21 

     dteHoliday(lngACount) = DateSerial(lngCount, 3, 1) + lngDay + _ 
       (lngDay > 48) + 6 - ((lngCount + lngCount \ 4 + _ 
       lngDay + (lngDay > 48) + 1) Mod 7) 
    Next 


    For lngCount = 1 To DateDiff("d", dteStart, dteEnd) 
     dteCurr = (dteStart + lngCount) 
     If (Weekday(dteCurr) <> 1) And (Weekday(dteCurr) <> 7) Then 
      blnHol = False 
      For dteLoop = 0 To UBound(dteHoliday) 
      'MsgBox dteHoliday(dteLoop) & " " & dteLoop 
       If (dteHoliday(dteLoop) = dteCurr) Then 
       blnHol = True 
       End If 
      Next dteLoop 
      If blnHol = False Then 
       lngTotal = lngTotal + 1 
       'MsgBox dteCurr 
      End If 
     End If 
    Next lngCount 

BusinessDays = lngTotal 
Else    'Add 
BusinessDays = -1 ' add 
End If 'add 


err_workingDays: 
MsgBox "Error No: " & Err.Number & vbCr & _ 
"Description: " & Err.Description 
Resume exit_workingDays 



End Function 
+0

Plus précisément - Si j'exécute la requête et fais défiler vers le bas, une erreur apparaît "Indice hors limites" et met en surbrillance la ligne: – gfuller40

+0

ReDim dteHoliday (lngDiff) – gfuller40

Répondre

0

Le code échoue lorsque Year(dteStartDate) > Year(dteEndDate)

+0

Ceci est vraiment un commentaire, pas une réponse à la question.Veuillez utiliser "ajouter un commentaire" pour laisser un commentaire à l'auteur. – Conner

+0

@Conner: J'apprécie votre examen des problèmes potentiels sur StackOverflow. Je vous assure, cependant, que je voulais dire cela comme une réponse. Le PO déclare dans sa question qu'il est «à 99% sûr que c'est un problème de données». J'identifiais simplement les données qui causeraient l'erreur. J'ai laissé le soin au PO de trouver les dossiers incriminés et de prendre toutes les mesures correctives qu'il estimait appropriées. – mwolfe02

+0

J'espère que ma critique ne vous a pas offensé. Le processus de révision est actuellement en version bêta et il a donc encore besoin de quelques corrections. L'un de ces problèmes est que les réviseurs ne peuvent pas afficher le contexte complet de la question. Ainsi, j'ai seulement votre question à regarder. J'ai évalué que cette réponse particulière est plutôt courte et pourrait facilement être transformée en commentaire. Je pense que SO cherche à incorporer des réponses qui incluent plus d'explications qui pourraient bénéficier aux futurs utilisateurs de problèmes moins localisés. Je sais que ce n'est pas toujours possible, mais j'ai juste pris une décision instinctive en quelques secondes. Cordialement. – Conner

0

Vous ne pouvez pas ReDim un tableau à une valeur négative.

Lorsque lngEYear < lngYear, lngDiff sera inférieur à zéro.

0

Je ne suis pas sûr que cette ligne:

If IsDate(dteStartDate) And IsDate(dteEndDate) Then 'added here begin 

est nécessaire, puisque vous aurez des erreurs de type Mismatch si vous essayez de nourrir d'autres types de valeurs dans la fonction. Dans tous les cas, vous aussi/au lieu devriez avoir quelque chose comme:

If dteStartDate <= dteEndDate Then 

avec la partie Else retourner une réponse « connue mauvaise », la façon dont votre code produit ici:

Else    'Add    
    BusinessDays = -1 ' add    
End If 'add    

Ceci est juste une l'expansion des réponses déjà posté par Jim Anderson et mwolfe02 . Si vous acceptez cette réponse/votez-la, vous devriez également voter pour eux ...

+0

Étant donné que les variables 'dteStartDate' et' dteEndDate' sont déclarées en tant que type Date, la fonction IsDate renvoie toujours la valeur true. Cependant, le passage d'une chaîne à IsDate ne provoquera pas d'erreur d'incompatibilité de type. Au contraire, si la chaîne peut être convertie en date, la fonction retournera vrai; sinon, il retournera faux. – phoog

0

Vous obtenez une incompatibilité de type de données parce que vous avez déclaré les paramètres en tant que type Date. Alors qu'une colonne Date/Time dans la base de données peut contenir une valeur null, une variable Date dans VBA ne peut pas. Vous devez donc déclarer les paramètres comme Variant s, et effectuer une vérification de type en tête de votre fonction.

Cela signifie que mon commentaire à une autre réponse (dire que IsDate retournera toujours vrai ici) est trompeur. Plutôt que de supprimer la vérification sans signification IsDate, vous devez rendre le contrôle significatif en modifiant le type de paramètre de Date à Variant.

Espérons que cela aide.