Bericht in Acccess97

Ich habe eine Tabelle, in der ich in der 1. Spalte LV-ummern (Tiefbau) erfaßt habe und in den nächsten Spalten mit der Überschrift 1.Abrechnung 2.Abrechnung 3.Abrechnung usw sind Werte erfaßt. Allerdings sind in der Tabelle nur einige Felder ausgefüllt. Also z.B. im LV-Nummer 001:

1.Abrechnung = 2 Stück
3.Abrechnung = 5 Stück

Ich brauche nun einen Bericht, der mir diese Tabelle wie folgt ausgibt:
LV-Nr. 001
1.Abrechnung 2Stück
3.Abrechnung 5Stück

d.h. er soll mir für jede LV-Nummer nur die Abrechnungen hinschreiben, bei denen auch tatsächlich Werte vorhanden sind.
bei LV-Nr.1 dürfte also nur die Werte der 1. und 3. Abrechnung erscheinen. In meiner Auswertung werden alle Abrechnungsnummer hingeschrieben, auch die, wo keine Werte vorhanden sind. Es gibt also ganze Blätter, auf denen kein einzige Wert erscheint, sondern nur die Feldüberschriften: Abrechnung 1 bis 200

Wie kann ich das machen???
Gibt es eine Eigenschaft, beim Formatieren des Berichts Textfelder wegzulassen, wenn diese leer sind

Hallo.
Der generelle Weg wäre, statt des Originalfeldes eine Formel der Form "=Wenn [Originalfeld] Ist Nicht Null;[Originalfeld];Null) anzugeben. Das muß für alle Einzelfelder passieren. Außerdem solltest Du die Eigenschaft „Verkleinerbar“ des Berichtsbereiches auf „Ja“ drehen. Dann werden nur NichtNull-Felder ausgegeben.
Ansonsten kannst Du auch die Abfrage entsprechend bauen, so daß die Felder mit Inhalt Null gar nicht erst für die Report-Erzeugung herangezogen werden.
Der dritte Weg ist eine Ereignisprozedur im Ereignis „Beim Drucken“, die im Falle von Inhalt Null den Befehl DoCmd.CancelEvent ausführt.
Detailliertere Infos von [email protected].
Gruß kw

Hi Blockus, hi Klaus,

sorry, aber ich glaube nicht, dass die Vorgehensweisen 1 und 3 von Klaus das gewünschte Ergebnis liefern werden (nicht böse sein, falls ich mich irren sollte :o), da so wohl nur Leerstellen bzw. Leerzeilen bei den Nullfeldern ausgegeben werden (das sieht ja dann wohl doch ziemlich unschön aus). Ich würde mal sagen, der von Klaus vorgeschlagene Weg Nr. 2 führt zum Ziel:

Die Tabelle sieht ja wohl irgendwie so aus:

LVNummer | Abrechnung1 | Abrechnung2 | Abrechnung 3
---------------------------------------------------
001 | 2 | 3 | 1
002 | 1 | | 2
003 | | 7 | 

Viel „schöner“ (zumindest meiner Meinung nach) wäre allerdings 'ne Tabelle in folgendem Format:

LVNummer | Abrechnungsnummer | Abrechnung 
------------------------------------------
001 | 1 | 2 
001 | 2 | 3 
001 | 3 | 1 
002 | 1 | 1 
002 | 3 | 2 
003 | 7 | 3 

Dazu muss man jetzt entweder das Datenbankdesign überdenken bzw. überarbeiten (wozu ja wohl sicherlich keiner Bock hat), oder man verwendet folgende Abfrage, um aus der Tabelle die gewünschte Wertemenge zu bilden:

select LVNummer, 1 as Abrechnungsnummer, Abrechnung1 as Abrechnung from Tabelle where not isnull(Abrechnung1)
union select LVNummer, 2, Abrechnung2 from Tabelle where not isnull(Abrechnung2)
union select LVNummer, 3, Abrechnung3 from Tabelle where not isnull(Abrechnung3)
order by 1, 2

Damit hat man dann bei den Berichten keine Nullfelder mehr, man muss halt im Bericht die Gruppiermöglichkeit verwenden oder bei bestimmten Textfeldern die Eigenschaft „Duplikate ausblenden“ eventuell auf „Ja“ setzten. Außerdem wird es jetzt schwerer, die einzelnen Abrechnungen zu einer LV-Nummer auf der selben Zeile zu schreiben (wenn Du DAS willst, kannst Du alles vergessen, was ich grad erzählt hab und machst das einfach mit einer einzigen Formel mit diversen "Wenn"s und "&"s - Klaus hat da sowas gleich zu Anfang vorgeschlagen).

Ich hoffe, dass das jetzt auch einigermaßen okay war, was ich da geschrieben hab.

Liebe Grüße
Lala

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Hallo Lala,

danke für die schnelle Antwort auf meine Frage. Ihre Tabelle ist wirklich viel besser als meine. Da ich die Datenstruktur nicht ändern möchte (Daten sind aus excel importiert) habe ich Ihre SQL-Anweisung ausprobiert. Klappt prima. Allerdings gibt es ein neues Problem. Ich habe über 60 Abrechnungsnummern und wenn ich Ihre SQL-Anweisung über Abrechnung20 hinaus erweitere, bekomme ich die Fehlermeldung:
SQL zu komplex

Kann man in dieser Anweisung nicht eine Schleife einbauen: Für Abrechnung 1-60 : union select ???

Vielen Dank noch mal im voraus für Ihre Bemühungen.

Hi Blockus, hi Klaus,

sorry, aber ich glaube nicht, dass die Vorgehensweisen 1 und 3
von Klaus das gewünschte Ergebnis liefern werden (nicht böse
sein, falls ich mich irren sollte :o), da so wohl nur

Bin ich nicht. Aber durch das „Verkleinern“ des Berichtsbereiches schafft man es, daß keine Leerzeilen ausgegeben werden. Ist wirklich so …
kw

Hi Blockus,

erstmal kannst Du mich natürlich gerne duzen (mach ich Dir gegenüber ja schließlich auch ;o).
Aber zurück zu Deinem Problem: Okay, sechzig Unions auf einmal, da kann ich mir vorstellen, dass das Probleme gibt.
Leider fällt mir aber nichts anderes ein, was ich als „schöne“ Lösung bezeichnen würde. Na ja, angenommen, die Daten aus der Excel-Datei werden bei jeder größeren Änderung neu importiert: Hier ist es sicher sinnvoll sie gleich in so 'ne Tabellenform zu bringen, wie ich’s im letzten Artikel beschrieben hab (dazu die Tabelle ein einziges Mal ohne Daten erstellen und beim Importieren in einer Prozedur dafür sorgen, dass zuerst alle eventuellen alten Daten gelöscht werden und dann in 'ner For-Schleife sechzig Mal 'ne Insert-Query aufrufen - irgendwie so…). Aber da es ja eher wahrscheinlich ist, dass die Excel-Tabelle verknüpft ist (also nicht explizit importiert wird) muß man sich irgendwas anderes überlegen.
Meine Idee: Im Detailbereich des Berichts (Datenherkunft ist die Originaltablle, also die mit 61 Spalten) gibt es ein Textfeld mit der LV-Nummer und eines, das die gesamten Abrechnungsdaten enthält. Bei letzterem ist die Eigenschaft „Vergrößerbar“ auf „Ja“ zu setzen.
Nun könnte man sich vorstellen, in das besagte vergrößerbare Textfeld einfach 'nen langen Ausdruck etwa der Form

=Wenn(Nicht IstNull([Abrechnung1]);"Abrechnung 1:" & ([Abrechnung1]) & " Stück" & Zchn(13) & Zchn(10)) & Wenn(Nicht IstNull([Abrechnung2]);"Abrechnung 2:" & ([Abrechnung2]) & " Stück " & Zchn(13) & Zchn(10)) ...

reinzuschreiben. Leider meckert dann aber das doofe Access rum, dass man nur 2048 Zeichen zur Verfügung hätte.
Na ja, 'n Ausweg wäre ein Ausdruck der Form

=Ausgabe(array([Abrechnung1]; [Abrechnung2]; ... ; [Abrechnung60]))

wobei „Ausgabe“ 'ne Funktion sein soll, die irgendwo noch genauers definiert werden muss und halt einen entsprechenden String zurückgeben sollte.
Allerdings mag Access auch dieses nicht: Fehlermeldung lautet irgendwas mit „Ausdruck zu komplex“.
Na ja, das einzige was mir dann noch so eingefallen ist, ist, das zweite für die Abrechnungen bestimmte Textfeld (nennen wir es mal „Textfeld“) zuerst ungebunden zu lassen, stattdessen aber im Detailbereich „beim Formatieren“ folgende Ereignisprozedur zu
hinterlegen:

Private Sub Detailbereich\_Format(Cancel As Integer, FormatCount As Integer)
 Dim s As String, a As Variant, i As Integer
 s = ""
 a = Array([Abrechnung1], ... , [Abrechnung60])
 For i = LBound(a) To UBound(a)
 If Not IsNull(a(i)) Then
 If i \> 1 Then s = s & vbCr & vbLf
 s = s & "Abrechnung " & i & ": " & a(i) & " Stück"
 End If
 Next
 Me.Textfeld = s
End Sub

Soweit so gut, nur dass das Access jetzt meint, es wisse nicht, was [AbrechnungX] bedeute. Echt toll, ich hab zwar keine Ahnung warum das so ist (ich hasse VB!!!), aber jedenfalls kann man das verhindern, indem man dem Bericht ein unsichtbares Textfeld mit dem Steuerelementeinhalt „=[Abrechnung1] & [Abrechnung2] & … & [Abrechnung60]“ hinzufügt.
Jetzt klappt das soweit, obwohl ich das allerdings für 'ne ziemlich umständliche Lösung halte, aber vielleicht fällt Dir - oder irgendjemandem der den Artikel hier sonst noch liest - 'ja noch was besseres ein.

Bei Fragen kannste Dich gerne melden.

Liebe Grüße
Lala

PS: Mir ist grad noch was anderes eingefallen: Du kannst auch folgende Query erstellen:

select Nummer, Abrechnungen(Nummer) as Abrechnungen from Tabelle

um sie dann ganz einfach in 'nen Bericht mit zumindest einem Textfeld für die LV-Nummer und einem (größenveränderbaren) für
den (mehrzeiligen) String, der die Abrechnungen erhält, zu verwenden.
Die Funktion Abrechnungen muss natürlich zuerst noch separat definiert werden, sie bekommt die LV-Nummer übergeben und liefert ‚nen (wohl „mehrzeiligen“) String zurück, der die Abrechnungen beinhaltet. Dazu wird für jede einzelne Nummer ‚ne extra Query gestartet ("… where Nummer=‘…‘") und aus den 60 Ergebnisspalten der Rückgabestring gebildet.
Aber mir persönlich gefällt die obere Lösung besser, u. a. weil sie wohl auch schneller ist.
Übrigens kann man 'ne Query der Form: select Nummer, Abrechnung(array(Abrechnung1, … , Abrechnung60)) as Abrechnungen from Tabellen bzw. select Nummer, Abrechnungen(Abrechnung1, … , Abrechnung60) as Abrechnung from Tabelle vergessen, da Access das auch für zu komplex (?!?) hält.

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Hi Klaus, hi Blockus,

hey, das funktioniert ja wirklich!!!
Also Blockus, einfach alles vergessen, was ich da vorhin geschrieben hab und in Deinem Bericht die 60 Textfelder untereinander hinzufügen, bei denen die „Verkleinerbar“-Eigenschaft überall auf „Ja“ setzen, ebenso beim Detailbereich selber.
Wenn Du jetzt keinen vertikalen Abstand zwischen den 60 Textfeldern gelassen hast, entstehen so wirklich keine Leerzeilen.
Klaus’ Lösung ist wirklich viel besser als das, was ich da vorgeschlagen hab.

Liebe Grüsse
Lala

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Hallo Lala,

ich habe doch Deinen ersten TIP VERWENDET. Danke nochmal. Das Problem mit zu komplex habe ich durch 2 Abfragen(select union) gelöst (jeweils 30 Felder packt access gerade noch) die ich im Bericht dann zusammenfüge.
Also noch mal Danke!!!

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]