Laden...
M
Benutzerbeschreibung
Konto auf Wunsch des Benutzers gesperrt

Forenbeiträge von Mike_on_Tour Ingesamt 48 Beiträge

14.12.2005 - 10:12 Uhr

Hallo,

das Problem mit der Anmeldung hatte ich auch. Nach ein paar Versuchen habe ich das aber auch hinbekommen.
Dazu war es aber notwendig, den Report direkt mit der Datenbank zu verbinden und auch anzumelden.

using CrystalDecisions.CrystalReports;
using CrystalDecisions.CrystalReports.Engine;
using CrystalDecisions.Shared;
...
privtae void Report_Load (object sender, System.EventArgs e)
{
  string strUserID = "USER_ID";  // hier die User-Kennung für die Datenbank eintragen
  string strPassword = "password";  // hier das Paßwort für die Datenbank eintragen

  Report_Berichte rpt1 = new Report_Berichte();

  rpt1.SetDatabaseLogon (strUserID, strPassword);

  crystalReportViewer1.ReportSource = rpt1;
}

Zur Zeit mache ich es aber so, daß alle Reports mit einem DataSet arbeiten. Dafür brauche ich keine Anmeldung. Das sieht dann z.B. so aus:

private void Report_Load (object sender, System.EventArgs e)
{
  Report_Berichte rpt1 = new Report_Berichte();

  dataSet1.TABELLE1.Clear();
  DataAdapter1.SelectCommand.CommandText = "SELECT * FROM TABELLE1";
  int i1 = DataAdapter1.Fill (dataSet1.TABELLE1);
  ...
  dataSet1.TABELLE5.Clear();
  DataAdapter5.SelectCommand.CommandText = "SELECT * FROM TABELLE5";
  int i5 = DataAdapter5.Fill (dataSet1.TABELLE5);

  rpt1.SetDataSource (dataSet1);

  rpt1.SetParameterValue ("Param_1", ReportParam1);  // Parameter zur Steuerung im Report

  crystalReportViewer1.ReportSource = rpt1;
}

Die Select-Anweisungen müssen natürlich entsprechend angepaßt werden.

mfG
Mike

13.12.2005 - 18:00 Uhr

Hallo herbivore,

jetzt wird es doch noch eine Diskussion:D. Nee, soweit liegen wir wohl gar nicht auseinander. Da es aber keine feste Vorschrift zum Programmieren gibt, hat eben jeder die Freiheit, es so zu machen, wie er glaubt oder weiß oder glaubt zu wissen. Ein Programmierer ist eben doch auch ein Künstler.

Was meinst du mit wirklich gelernt?

Na eben wirklich, so mit Schreibmaschine, Lochkarte und Lochstreifen halt. Da waren die Bits noch sichtbar und die Computer noch wahre Höllenmaschinen. Auf keine Fall wollte ich den Eindruck erwecken, daß Du (oder andere) nicht programmieren können. Falls Du es anders verstanden hast, bitte ich um Vergebung. Deine Beiträge sind es jedenfalls immer wert gelesen zu werden. Das Beste ist allerdings, daß Du Dein Wissen und Können hier weitergibst. Hier und da habe ich ja auch schon Anregungen „mitgenommen“.

mfG
Mike

13.12.2005 - 17:31 Uhr

Hallo,

ich habe auch mehrere Tabellen in einem Report. Bevor der Report angezeigt wird, führe ich ein SELECT über alle Tabellen aus. Im Report selbst habe ich dann die Tabellen untereinander verknüpft (visueller Verknüpfungsassistent / DB hinzufügen). Klappt ganz gut.

mfG
Mike

13.12.2005 - 17:03 Uhr

Hallo herbivore,

ich will hier jetzt keine große Diskussion anfangen, da mir auch die Zeit dafür fehlt (in 7 Tagen ist mein Job zu Ende). Aber ich bin der Meinung, daß ein Konstruktor dazu dient, einem Objekt gleich von Anfang an Attribute, Werte und Ressourcen zuzuweisen, also einen definierten Startzustand zu erzeugen. Alles andere sollte mit Events behandelt werden. In meinem Beispiel hat deshalb eine Routine zum Laden einer Datenbank nichts zu suchen. Das (Über)Schreiben im Konstruktor kann meiner Meinung nach auch dazu führen, daß bei Auftreten einer Ausnahme innerhalb des Konstruktors der Desktruktor nicht aufgerufen wird und deshalb die Ressourcen nicht freigegeben werden (nur von einem vollständig konstruierten Objekt wird der Destruktor aufgerufen).

Ich habe auch schon mehrfach Programme oder Teile davon gesehen, die ohne Grund im Konstruktor Code enthielten, den man auch in die Events hätte setzen können. Die Programme funktionieren natürlich genauso gut wie andere auch. Aber meiner Meinung nach ist das einfach schlechter Programmierstil. Ich halte es lieber mit dem Grundsatz, der IDE (die erstellt ja den Konstruktor einer Form) nur dann "ins Handwerk zu pfuschen", wenn es denn unbedingt sein muß (z.B. um Methoden zu erweitern). Im Übrigen findet man das auch in zahlreichen Büchern, wo einfach der Code im Konstruktor geschrieben wird. Man sollte aber daran denken, daß die Beispiele nur der Erklärung und Veranschaulichung dienen und oftmals aus Platzgründen so kompakt geschrieben werden.

Ich für meinen Teil, werde es also auch weiterhin so machen, wie ich es gelernt (ich meine damit wirklich gelernt !!!) habe und hoffe es ist ein guter Programmierstil. Damit bin ich bisher ganz gut gefahren und es hat auch noch kein Mitstreiter bzw. Nachfolger darüber „gemeckert“.

Übrigens hat sich mein Problem in Wohlgefallen aufgelöst. Möglicherweise ist beim Austausch des Sourcecodes zwischen den Kollegen so Einiges (im Konstruktor) durcheinander geraten. Keiner war’s gewesen, keiner hat‘s gesehen (ich auch nicht 😦). Also wie immer.

Ach ja, das Laden der Tabelle habe ich jetzt versuchsweise mal ins Form_Activated "gebastelt". Damit fällt die Wartezeit beim Form_Load weg.

mfG
Mike

12.12.2005 - 18:33 Uhr

Hallo,

damit läßt sich aber das Verhalten im Debug-Mode nicht klären.

@herbivore

warum benutzt du Form_Load?

Weil es vielleicht dafür da ist, all das zu tun, was beim Laden eines Forms getan werden muß ? OK, das Laden der Tabelle kann ich auch wo anders machen, aber sicher nicht im Konstruktor.

Form.Load braucht man nur, wenn man auf das Laden eines anderen Forms reagieren will.

Wo steht das ?

@svenson
Damit bin ich doch einverstanden.

Trotzdem noch mal die Frage, ob es eine Erklärung für den erneuten Durchlauf des Load-Events beim Close gibt.

mfG
Mike

09.12.2005 - 11:31 Uhr

Hallo zusammen,

ich habe eine DB-Anwendung. Im Form_Load-Ereignis lade ich ich die DB mit DataAdapter.Fill(). Die DB besteht aus über 25000 Datensätzen und das Laden dauert etwas. Danch stehen alle Daten zur Verfügung. Zum Beenden gibt es einen Button, der nur die Close()-Funktion des Formulars aufruft. Für das Ereignis Form_Close() gibt es keinen Code. Das Schließen des Forms dauert genauso lange, wie das Laden der Form. Im Debugger wird auch tatsächlich nochmal die komplette Form_Load-Routine durchlaufen. Warum ?

Beispiel-Code:

private void Form_Load(object sender, System.EventArgs e)
{
  ...
  dataSet1.TABELLE.Clear();
  DataAdapter1.Fill (dataSet1.TABELLE);
  ...
}

private void buttonClose_Click(object sender, System.EventArgs e)
{
  this.Close();
}

private void Form_Closed(object sender, System.EventArgs e)
{
  // nothing
}

mfG
Mike

08.12.2005 - 16:06 Uhr

Hallo,

ich habe mit Crystal Reports (VS.net) einen Report erstellt mit folgendem Aufbau:

Berichtskopf (wird unterdrückt)
Seitenkopf (enthält u.a. Datum, Seiten-Nr.)
Gruppenkopf 1 (enthält u.a. Name, Adresse des Empfängers)
Gruppenkopf 2a (enthält Spaltenüberschiften für Detail a)
Gruppenkopf 2b (enthält Spaltenüberschiften für Detail b)
Gruppenkopf 2c (enthält Spaltenüberschiften für Detail c)
Details a (enthält Daten für Filter a)
Details b (enthält Daten für Filter b)
Details c (enthält Daten für Filter c)
Gruppenfuß 2 (enthält Daten über den Absender der Gruppe 2)
Gruppenfuß 1 (wird unterdrückt)
Seitenfuß
Berichtsfuß (wird unterdrückt)

Der Gruppenfuß 2 soll immer am Ende einer Seite ausgegeben werden. Dazu habe ich die Option "Am Ende der Seite drucken" aktiviert. Aber bisher wird der Gruppenfuß nur am Ende der Gruppe gedruckt. Außerdem soll nach dem Ende der Gruppe 2 eine neue Seite begonnen werden. Die entsprechende Option ist ebenfaslls aktiv und funktioniert bereits.

Wie kann ich den Gruppenfuß auf jeder Seite drucken ?

mfG
Mike

07.12.2005 - 18:23 Uhr

Hallo,

eigentlich hat jede Textbox die schöne Eigenschaft 'CharacterCasing'. Dort läßt sich ganz einfach einstellen, ob normale Shreibweise oder Groß- bzw. Kleinbuchstaben.

Eine SQL-Abfrage sollte in etwa so aussehen:

SELECT * FROM tabelle WHERE (UPPER(feld) = '" + textBox.Text.ToUpper() + "');

mfG
Mike

29.11.2005 - 16:17 Uhr

Hallo,

natürlich kannst Du mit Crystal Reports auch im Querformat anzeigen und drucken. Bedingung hierfür ist die korrekte Druckereinstellung. Du findest das unter: (rechte Maustaste - Designer - Druckereinstellungen). Hier wählst Du einfach einen Drucker aus und gibst als Papier-Ausrichtung 'Querformat' an. Fertig.

Mike

28.11.2005 - 19:17 Uhr

Also, wenn ich es richtig verstanden habe, willst Du ja nicht wirklich den ersten Montag eines Jahres errechnen, sondern den Montag einer Woche. Da das besonders zum Jahreswechsel etwas knifflig wird, solltest Du als Ausgangsbasis immer mit dem Montag der KW 1 anfangen zu rechnen. Dann addierst Du einfach Deine ausgewählte KW minus 1 multipliziert mit 7 dazu und schon hast Du den Montag Deiner KW. Klingt kompliziert ? Ich habe es nicht probiert, aber so sollte es funktionieren:

public DateTime GetMonday (int KW, int Jahr)
{
  // Datum für den 4.1.
  DateTime vierterJanuar = new DateTime (Jahr, 1, 4); 
  // Montag der 1. KW ermitteln (Mo=1 ... So=7)
  int MoKW1 = (((int)vierterJanuar.DayOfWeek + 6) % 7) + 1; 
  // Datum vom Montag ermitteln
  DateTime dtMonday = vierterJanuar.AddDays (- (MoKW1 - 1));
  // Montag der ausgewählten KW ermitteln
  return dtMonday.AddDays ((KW - 1) * 7);
}

mfg
Mike

28.11.2005 - 15:35 Uhr

Hallo,

meinst Du etwa "Buildaktion" ? Die möglichen Optionen lauten: 'Keine', 'Kompilieren', 'Inhalt' und 'Eingebettete Ressource'. Ich verwende (standardmäßig) 'Eingebettete Ressource'. Ich sollte es mal mit 'Keine' probieren, oder ?

Mike

28.11.2005 - 14:08 Uhr

Hallo,

wir hatten vor ein paar Wochen schon mal das Thema. Schau mal dort rein, dann weißt Du auch, wie Du den Montag rechnerisch ermitteln kannst.
Montag der Woche errechnen

mfG
Mike

25.11.2005 - 09:49 Uhr

Hallo,

ich habe mir auch noch mal die Hilfe vorgenommen. Wenn Du nach 'Crystal Report Viewer' suchst, bekommst Du die Auswahl zwischen 'Web Forms Viewer' und 'Windows Forms Viewer'. Nimm 'Web Forms Viewer' und Du bekommst am Ende der Seite einen Link zu 'ReportDocument' (ReportSource). Zeige dann eine Liste aller Elemente der ReportDocument-Klasse an. Dort findest Du die Eigenschaft 'ExportOptions' und die Methoden 'Export', 'ExportToDisk' und 'ExportToStream'. Wenn Du außerdem in der Hilfe nach 'Crystal Reports' suchst, findest Du auch einen Punkt 'Exportieren'. Wähle dann 'Exportieren webbasierter Berichte'. Hier steht, daß neben PDF auch MS-Formate exportiert werden können. Da ist sogar ein Beispiel für PDF dabei. Schau Dir das mal an, vielleicht hilft es Dir weiter. Mehr weiß ich aber auch nicht.

mfG
Mike

25.11.2005 - 09:31 Uhr

Hallo,

@ tb : Das klingt ja erst mal kompliziert. Aber ich schau mir mal den Link an, vielleicht ist es ja eine tolle Sache. Kleines Problem dabei ist, daß ich das Programm nur anfange zu schreiben und andere es fortsetzen müssen. Die sollten das auch verstehen (bis jetzt habe ich da aber erhebliche Bedenken). Na ja, soll aber nicht mein Problem werden.

@ svenson : schluck
Klingt auch nicht einfacher. Werde mich aber auch damit mal beschäftigen. Hast Du evtl. einen Codeschnipsel ?

@ alle: Hatte schnell noch einen Test mit Delphi (V5) gemacht. Da gibt es ein Maskenformat. Hat wesentlich besser und einfacher funktioniert, wenn auch nicht ganz 100%ig. Sowas müßte eben auch mal Microsoft können. Den Delphi-Erfinder Heilsberg haben Sie ja schon (Ähnlichkeiten zwischen Delphi und C# sind also nicht rein zufällig).

Danke bisher.

mfG
Mike

24.11.2005 - 17:42 Uhr

Der CrystalReportViewer für WinForms enthält eine Toolbar, u.a. zum Navigieren im Report. Dort befindet sich standardmäßig auch ein Button zum Exportieren des Reports (Briefumschlag mit Pfeil).

Gibt es die Toolbar bzw. den Button auch im ReportViewer für WebForms ?

Mike

24.11.2005 - 16:48 Uhr

Hi,

Sorry, da habe ich jetzt auch erst mal keine Idee mehr. Offensichtlich funktionieren die WebForms anders. Ich werde mir nochmal alles in Ruhe anschauen.

mfG
Mike

PS:

... cool das Du so hilfreich bist Sag das aber nicht meinem "Bewährungshelfer".

24.11.2005 - 16:08 Uhr

Hallo AlfameisterT,

zu 1.) bisher keine Änderungen
zu 2.) wenn ich einen geändeten Report verwenden will, ohne das Projekt neu zu erstellen, dann wird der alte Report angezeigt. Ist doch irgendwie unlogisch, oder ? Liegt es vielleicht daran, daß meine Reports auf einem DataSet basieren ?

mfG
Mike

24.11.2005 - 16:02 Uhr

Hallo tb,

hast Du dafür ein kleines Beispiel ?

24.11.2005 - 15:59 Uhr

Also, ich habe Deinen Code mal schnell überflogen (im wahrsten Sinne des Wortes). Kannst Du mal zum Test noch einen Button einfügen und im OnClick-Event folgendes schreiben:

private void XLSButtonOnClick(object sender, System.EventArgs e)
{
  string sXLSFileName = "Report.xls";

  try
  {
    crReportDocument.ExportToDisk (ExportFormatType.Excel, sXLSFileName);
  }
  catch (Exception ex)
  {
    throw ex;
  }
}

Wenn das so nicht funktioniert, dann versuche mal, immer dort wo Du diese Zeile hast

Umsatz_Standortübergreifend auswahl = new Umsatz_Standortübergreifend();

noch folgendes zu schreiben:

auswahl.SetDataSource(ReportSet);
this.CrystalReportViewer1.ReportSource = auswahl;
// die neue Zeile
crReportDocument.ExportToDisk (ExportFormatType.Excel, "Report.xls");

Die Variablen 'crReportDocument' und 'auswahl' sind eigentlich identisch, oder ? 'crReportDocument' gilt global für das Projekt, während 'auswahl' nur lokal in der jeweiligen Prozedur ist sind. Vielleicht ist auch das das Problem ?

mfG
Mike

24.11.2005 - 12:37 Uhr

... noch nicht so fitt bin im c#

Sorry, habe ich übersehen.

Also mit Report ist die Klasse des Report-Files gemeint. Du hast ja einen Report erstellt. Und den Namen des Reports (ohne *.rpt) gibst Du an. Mein Code soll ja auch nur als Beispiel dienen. Den Original-Code kann ich hier nicht eintragen, das sind über 1500 Zeilen. 😁

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.IO;
using CrystalDecisions.Shared;  // (!!!)

namespace ...
{
  public class FormReport : System.Windows.Forms.Form
  {
    ...
    #region Vom Windows Form-Designer generierter Code
    ...
    #endregion

    public string Param1 = "";
    // hier die Klasse des Report-Files (*.rpt) angeben
    // wenn das Report-File (*.rpt) den Namen "Report.rpt" hat, hier Report angeben
    Report rpt = new Report(); 

    private void FormReport_Load(object sender, System.EventArgs e)
    {
      string sReportFileName = ReportFileDirectory + rpt.ResourceName.ToString();

      // hier noch anderen Code einfügen (z.B. Formulargröße usw.)
 
      dataSet1.TABLE1.Clear();
      DataAdapter1.Fill (dataSet1.TABLE1);

      rpt.SetDataSource (dataSet1);
      rpt.SetParameterValue ("Param_1", Param1);

      ReportViewer1.ReportSource = rpt;
      /*
      wenn Du ohne DataSet arbeitest, kannst Du auch nur einfach den Namen des 
      Report-Files (*.rpt) direkt übergeben und alles andere (DataSet, DataAdapter usw.) 
      weglassen

      ReportViewer1.ReportSource = sReportFileName;
      */ 
    }

    private void button1_Click(object sender, System.EventArgs e)
    {
      string sPDFFileName = DateTime.Today.ToString("yyyy-MM") + "-" + Param1 + ".pdf";

      // hier noch anderen Code einfügen (z.B. prüfen, ob File vorhanden)
 
      rpt.ExportToDisk (ExportFormatType.PortableDocFormat, PDFFileDirectory + sPDFFileName);

      // hier noch anderen Code einfügen (z.B. File anzeigen)
    }
    ...
  }
}

Statt

rpt.ExportToDisk (ExportFormatType.PortableDocFormat, PDFFileDirectory + sPDFFileName);

mußt Du für den Export nach XLS eben schreiben

rpt.ExportToDisk (ExportFormatType.Excel, XLSFileDirectory + sXLSFileName);

Und nicht vergessen, die Variablen XLSFileDirectory und sXLSFileName zu definieren.

Und wenn Du ohne DataSet arbeitest, reicht es eigentlich aus, nur den Namen der Report-Datei an den ReportViewer zu übergeben (siehe Code). Dann kann man auch die Klasse des Reports weglassen.

Mike

24.11.2005 - 09:13 Uhr

Also, in groben Zügen sieht mein Programm so aus:


public string Param1 = "";
Report rpt = new Report();   // das RPT-File

private void FormReport_Load(object sender, System.EventArgs e)
{
  string sReportFileName = ReportFileDirectory + rpt.ResourceName.ToString();

  dataSet1.TABLE1.Clear();
  DataAdapter1.Fill (dataSet1.TABLE1);

  rpt.SetDataSource (dataSet1);
  
  rpt.SetParameterValue ("Param_1", Param1);

  ReportViewer1.ReportSource = rpt;
}

private void button1_Click(object sender, System.EventArgs e)
{
  string sPDFFileName = DateTime.Today.ToString("yyyy-MM") + "-" + Param1 + ".pdf";

  rpt.ExportToDisk (ExportFormatType.PortableDocFormat, PDFFileDirectory + sPDFFileName);
}

Nachdem die PDF-Datei erstellt ist, wird sie (in meinem Fall) gleich per Mail verschickt. Aber prinzipiell kannst Du alles auch ohne Button-Click machen. Schreibe alles einfach in den gleichen Anweisungsblock (z.B. Form_Load).

mfG
Mike

23.11.2005 - 19:01 Uhr

Ich habe zwar noch keine XLS mit Crystal Reports erstellt, aber dafür jede Menge PDFs. Aber XLS müßte so gehen:

rpt.ExportToDisk (ExportFormatType.Excel, "filename.xls");

Einfach mal probieren.

Mike

23.11.2005 - 18:51 Uhr

Hallo Dexter,

Jetzt hast du statt den nullen, leerzeichen drin.

Ja, die bleiben dann aber auch drin.

Ich dachte mehr an eine Variante, wo der Inhalt des Feldes unverändert bleibt, aber die Anzeige der Daten "manipuliert" wird. Deshalb möchte ich gern (wenn möglich) die Format-Eigenschaft der Spalte nutzen. Wenn das nicht geht, bleibt mir nur das übrig, was Du beschrieben hast. 🙁

mfG
Mike

23.11.2005 - 18:35 Uhr

Hallo zusammen,

ich habe ein Datagrid, indem alle Daten einer DB-Tabelle angezeigt werden sollen. Ein Feld der Tabelle liefert mir einen String mit mehreren Zahlen in der Form "003006009012024". Ich möchte das Feld nun so anzeigen, daß aus den Nullen ein Leerzeichen wird, also "3 6 9 12 24". Beim zurückschreiben in die DB muß dann wieder der String "003006009012024" entstehen.

Kann man sowas mit der Format-Eigenschaft der Spalte machen ? Oder gibt es eine andere Lösung ?

Mike

23.11.2005 - 12:16 Uhr

Copy&Paste-Fehler?

Aber 100%ig. Danke für den Hinweis.

Aber mein Problem besteht immer noch. Momentan umgehe ich das Problem, indem ich im Form_Load ca. 20 Zeilen extra das programmiere, was im Designer nicht funktionieren will.

Verwendet denn niemand diese mehrspaltige ComboBox ?

mfG
Mike

22.11.2005 - 09:34 Uhr

Hallo,

ich verwende zur Zeit (Test) das Control MTGCComboBox (von Claudio Di Flumeri, Massimiliano Silvestro, Version 1.0 vom 20.10.2004) und habe einige Probleme. Ich habe im Designer alle Einstellungen so gewählt, daß die ComboBox direkt mit einer DB-Tabelle geladen wird und 4 Spalten anzeigt, also u.a.:


BorderStyle = MTGCComboBox.TipiBordi.FlatXP; 
DropDownStyle = MTGCComboBox.CustomDropDownStyle.DropDownList;
LoadingType = MTGCComboBox.CaricamentoCombo.DataTable; 
ColumnNum = 4;
ColumnWidth = "60;200;60;20";
DataSource = dataSet1;
DisplayMember = "Table1.BEZ"
SourceDataString = new string[] {"KURZ","BEZ",""KOST","PMNR"};
SourceDataTable = dataSet1.Table1;
ValueMember = "Table1.KURZ";

Das Programm funktioniert damit einwandfrei. Wenn ich aber das fertige Formular erneut im Designer öffne, erhalte ich einige Fehlermeldungen:
Die Variable 'CaricamentoCombo' wurde nicht deklariert oder nicht zugeordnet.
Die Variable 'TipiBordi' wurde nicht deklariert oder nicht zugeordnet.
Die Variable 'CustomDropDownStyle' wurde nicht deklariert oder nicht zugeordnet.
Außerdem gehen alle Einstellungen verloren, die mit dem direkten Zugriff auf die DB-Tabelle zusammenhängen: u.a. SourceDataString, SourceDataTable

Wer hat Erfahrung mit dem Control ?

09.11.2005 - 17:54 Uhr

Hallo,

ich habe mit Crystal Report (im VS) eine Liste erstellt. Am Seitenende muß ich den Namen der Reportdatei (*.rpt) schreiben. Dazu verwende ich das Spezialfeld "Dateipfad und -name". Das funktioniert im Prinzip auch. Aber aus unerfindlichen Gründen wird der Report in den User-Temp-Ordner geladen und dort ausgeführt. Das hat zur Folge, daß nicht der echte Name des Reports (z.B. "Report_Anforderung.rpt") angezeigt wird, sondern der Name des Temp-Reports (z.B. "C:\DOCUME1\haufa228\LOCALS1\Temp\temp_55fa4a3f-8b9b-4eb4-bf93-8e8e0665db88.rpt").

Wenn ich einen Report ändern muß, muß ich immer das ganze Projekt neu übersetzen. Es muß doch möglich sein, nur den Report zu ändern.

Hat jemand ein oder zwei Ideen dazu ?

mfG
Mike

09.11.2005 - 16:55 Uhr

Hallo sra,

ich habe das Problem im Ereignis MouseUp gelöst (ist nicht meine Idee, habe ich auch irgendwo "geklaut"). Probiers mal so:

private void dataGrid1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
  // den Klick-Punkt ermitteln
  System.Drawing.Point pt = new Point (e.X, e.Y); 
  // Informationen zum Klick-Punkt ermitteln
  DataGrid.HitTestInfo hti = dataGrid1.HitTest (pt); 
  // Wurde in eine Datengrid-Zelle geklickt ?
  if (hti.Type == DataGrid.HitTestType.Cell) 
  { 
    // JA, die Zelle und die Zeile markieren
    dataGrid1.CurrentCell = new DataGridCell (hti.Row, hti.Column); 
    dataGrid1.Select (hti.Row); 
  } 
}

mfG
Mike

04.11.2005 - 09:04 Uhr

Hallo notorious.madeye,

also ich bin auch gerade dabei, so etwas zu programmieren. Allerdings habe ich ein paar Sachen anders gemacht. Ich habe im Designer die Eigenschaft

panel1.Dock=Fill

gesetzt. Außerdem reagiere ich dann noch ggf. auf das Ereignis

private void panel1_Layout(object sender, System.Windows.Forms.LayoutEventArgs e)
{
  ...
}

Eine Form setze ich dann so auf das Panel:

...
Form2 formAufPanel = new Form2();
formAufPanel.FormBorderStyle = FormBorderStyle.None;
formAufPanel.WindowState = FormWindowState.Maximized;
formAufPanel.TopLevel = false;
panel1.Controls.Add (fFormAufPanel);
formAufPanel.Show();
...

Allerdings habe ich im Programm die Maximize- und Minimize-Buttons für das Hauptfenster verboten. Dafür ermittle ich beim Programmstart die Bildschirmgröße und zeige das Programm in dieser Größe an:

...
// die Bildschirmgröße (ohne System-Tray) ermitteln
Rectangle rectScreenSize = Screen.GetWorkingArea (this);
// das Programm so groß darstellen, wie der Bildschirm ist
this.Top = 0;
this.Left = 0;
this.Width = rectScreenSize.Width;
this.Height = rectScreenSize.Height;
...

Bei mir funktioniert das sehr gut, auch bei verschiedenen Bildschirmgrößen.

mfG
Mike

26.10.2005 - 18:09 Uhr

Hallo zusammen,

es hat etwas gedauert, aber nun habe ich mir doch ein UserControl (mein erstes !) geschrieben. Es ist vielleicht noch nicht ganz ausgereift, aber es macht genau das, was ich will. Hier ist mal der Code dazu:

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;

namespace MIKE.UserControls
{
  /// <summary>
  /// Zusammenfassung für UserControl MonatJahrCounter.
  /// </summary>
  public class MonatJahrCounter : System.Windows.Forms.UserControl
  {
    /// <summary>
    /// die einzelnen Komponenten des Controls 
    /// </summary>
    private System.Windows.Forms.Button button1;
    private System.Windows.Forms.Button button2;
    private System.Windows.Forms.Label label1;
    // textBox1 wird nur verwendet, um den Focus von den Buttons wegzunehmen !!!
    private System.Windows.Forms.TextBox textBox1;   
    /// <summary>
    /// die Variablen des Controls
    /// </summary>
    private int iMonat = 0;                         // Monat als Zahl
    private int iJahr = 0;                          // Jahr als Zahl
    private string sMonatJahr = "";                 // Monat und Jahr (Format: "MMMM yyyy")
    private string sJahrMonat = "";                 // Jahr und Monat (Format: "yyyy-MM")
    private DateTime dtMonatJahr = DateTime.Today;  // Datum (Tag nicht auswerten)
    /// <summary> 
    /// Erforderliche Designervariable.
    /// </summary>
    private System.ComponentModel.Container components = null;

    public MonatJahrCounter()
    {
      // Dieser Aufruf ist für den Windows Form-Designer erforderlich.
      InitializeComponent();

      // TODO: Initialisierungen nach dem Aufruf von InitializeComponent hinzufügen
      dtMonatJahr = DateTime.Today;
      iMonat = dtMonatJahr.Month;
      iJahr = dtMonatJahr.Year;
      sMonatJahr = dtMonatJahr.ToString ("MMMM yyyy");
      sJahrMonat = dtMonatJahr.ToString ("yyyy-MM");
    }

    /// <summary> 
    /// Die verwendeten Ressourcen bereinigen.
    /// </summary>
    protected override void Dispose( bool disposing )
    {
      if( disposing )
      {
        if(components != null)
        {
          components.Dispose();
        }
      }
      base.Dispose( disposing );
    }

    #region Vom Komponenten-Designer generierter Code
    /// <summary> 
    /// Erforderliche Methode für die Designerunterstützung. 
    /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
    /// </summary>
    private void InitializeComponent()
    {
      System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(MonatJahrCounter));
      this.button1 = new System.Windows.Forms.Button();
      this.button2 = new System.Windows.Forms.Button();
      this.label1 = new System.Windows.Forms.Label();
      this.textBox1 = new System.Windows.Forms.TextBox();
      this.SuspendLayout();
      // 
      // button1
      // 
      this.button1.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
      this.button1.Image = ((System.Drawing.Image)(resources.GetObject("button1.Image")));
      this.button1.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
      this.button1.Location = new System.Drawing.Point(92, 0);
      this.button1.Name = "button1";
      this.button1.Size = new System.Drawing.Size(16, 10);
      this.button1.TabIndex = 1;
      this.button1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
      this.button1.Click += new System.EventHandler(this.button1_Click);
      // 
      // button2
      // 
      this.button2.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
      this.button2.Image = ((System.Drawing.Image)(resources.GetObject("button2.Image")));
      this.button2.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
      this.button2.Location = new System.Drawing.Point(92, 10);
      this.button2.Name = "button2";
      this.button2.Size = new System.Drawing.Size(16, 10);
      this.button2.TabIndex = 2;
      this.button2.Click += new System.EventHandler(this.button2_Click);
      // 
      // label1
      // 
      this.label1.BackColor = System.Drawing.SystemColors.Window;
      this.label1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
      this.label1.Location = new System.Drawing.Point(0, 0);
      this.label1.Name = "label1";
      this.label1.Size = new System.Drawing.Size(92, 20);
      this.label1.TabIndex = 3;
      this.label1.Text = "label1";
      this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
      // 
      // textBox1
      // 
      this.textBox1.Location = new System.Drawing.Point(0, 0);
      this.textBox1.Name = "textBox1";
      this.textBox1.Size = new System.Drawing.Size(20, 20);
      this.textBox1.TabIndex = 0;
      this.textBox1.Text = "textBox1";
      // 
      // MonatJahrCounter
      // 
      this.Controls.Add(this.label1);
      this.Controls.Add(this.button2);
      this.Controls.Add(this.button1);
      this.Controls.Add(this.textBox1);
      this.Name = "MonatJahrCounter";
      this.Size = new System.Drawing.Size(108, 20);
      this.Load += new System.EventHandler(this.MonatJahrCounter_Load);
      this.ResumeLayout(false);
    }
    #endregion

    /// <summary>
    /// MONAT - ruft den zugewiesenen Monat ab oder legt einen Monat fest 
    /// </summary>
    [Category("Datum")] 
    public int Monat
    {
      get
      {
        return iMonat;
      }
      set
      {
        if ((value >= 1) && (value <= 12))
        {
          iMonat = value;
        }
        else
        {
          if (value < 1)
          {
            iJahr--;
            iMonat = 12;
          }
          if (value > 12)
          {
            iJahr++;
            iMonat = 1;
          }
        }

        MonatJahrAktualisieren();
      }
    }

    /// <summary>
    /// JAHR - ruft das zugewiesene Jahr ab oder legt dieses fest 
    /// </summary>
    [Category("Datum")] 
    public int Jahr
    {
      get
      {
        return iJahr;
      }
      set
      { 
        if (value >= 0)
        {
          iJahr = value;
        }
        else
        {
          iJahr = 0;
        }

        MonatJahrAktualisieren();
      }
    }

    /// <summary>
    /// MONATJAHR - ruft das zugewiesene Datum in der Form "MMMM YYYY" ab
    /// </summary>
    [Category("Datum")] 
    public string MonatJahr
    {
      get
      {
        MonatJahrAktualisieren();
        
        return sMonatJahr;
      }
    }

    /// <summary>
    /// JAHRMONAT - ruft das zugewiesene Datum in der Form "YYYY-MM" ab
    /// </summary>
    [Category("Datum")] 
    public string JahrMonat
    {
      get
      {
        MonatJahrAktualisieren();
        
        return sJahrMonat;
      }
    }

    /// <summary>
    /// DATUM - ruft das zugewiesene Datum ab oder legt es fest (Tag nicht auswerten)
    /// </summary>
    [Category("Datum")] 
    public DateTime Datum
    {
      set
      {
        Monat = value.Month;
        Jahr = value.Year;
        
        MonatJahrAktualisieren();
      }
      get
      {
        return dtMonatJahr;
      }
    }

    /// <summary>
    /// Funktion zum Zählen des Monats (unter Berücksichtung des Jahreswechsels)
    /// </summary>
    /// <param name="Richtung">Richtung der Zählung (vorwärts = 1, rückwärts = -1)</param>
    private void MonatZaehlen (int Richtung)
    {
      // Monat zählen
      iMonat = iMonat + Richtung;
      
      // wird Monat kleiner als 1 (Januar)
      if (iMonat < 1)
      {
        // dann 1 Jahr abziehen
        iJahr--;
        // und Monat auf 12 (Dezember) setzen
        iMonat = 12;
      }
      
      // wird Monat größer 12 (Dezember)
      if (iMonat > 12)
      {
        // dann 1 Jahr addieren
        iJahr++;
        // und Monat auf 1 setzen (Januar)
        iMonat = 1;
      }
    }

    /// <summary>
    /// Funktion zur Aktualisierung der Variablen nach Änderung von MONAT und JAHR
    /// </summary>
    private void MonatJahrAktualisieren()
    {
      dtMonatJahr = Convert.ToDateTime ("01." + iMonat.ToString("00") + "." + iJahr.ToString("0000"));
      sMonatJahr = dtMonatJahr.ToString("MMMM yyyy");
      sJahrMonat = dtMonatJahr.ToString("yyyy-MM");
      label1.Text = sMonatJahr;
    }

    /// <summary>
    /// einen Monat vorwärts zählen (Button 1)
    /// </summary>
    private void button1_Click(object sender, System.EventArgs e)
    {
      MonatZaehlen (1);
      MonatJahrAktualisieren();
      textBox1.Focus();   // der Focus wird vom Button genommen
      this.OnClick (e);
    }

    /// <summary>
    /// einen Monat rückwärts zählen (Button 2)
    /// </summary>
    private void button2_Click(object sender, System.EventArgs e)
    {
      MonatZaehlen (-1);
      MonatJahrAktualisieren();
      textBox1.Focus();   // der Focus wird vom Button genommen
      this.OnClick (e);
    }

    /// <summary>
    /// UserControl laden
    /// </summary>
    private void MonatJahrCounter_Load(object sender, System.EventArgs e)
    {
      // alle Variablen aktualisieren
      MonatJahrAktualisieren();
      textBox1.Focus();   // der Focus wird vom Button genommen
    }
  }
}

In die 2 Buttons habe ich noch eine kleines Bild mit Pfeilen (nach oben und nach unten) geladen (Bitmap mit 7x4 Pixel).

So, und weil es so einfach war, dürft Ihr den Code auch verwenden. Viel Spaß wünscht

Mike

19.10.2005 - 15:14 Uhr

Hallo CB.NET,

Du solltest Deine DB-Datumsfelder so setzen:

DBDatumFeld = Convert.DBNull;

Später solltest Du abfragen können:

if (Convert.IsDBNull (DBDatumFeld))

Die Hilfe sagt dazu:
"Convert.IsDBNull" ... gibt einen Wert zurück, der angibt, ob das angegebene Objekt vom Typ DBNull ist.

Hilft Dir das ?

mfG
Mike

19.10.2005 - 10:18 Uhr

Hallo,

ich habe eine Datenbank mit über 1500 Einträgen zu Personen, u.a. Name, Abteilung, Telefon, E-Mail. Die Einträge zu den Feldern Name und Abteilung sind fast komplett vorhanden. Außerdem gibt es noch einzelne Einträge zu Telefon und keine Einträge zu E-Mail (Adresse). Ziel ist das automatische Versenden von Mails an ausgewählte Personen mit Hilfe von Outlook (V2002). Da die E-Mail-Adressen jedoch fehlen, möchte ich einen Abgleich mit dem Adressbuch von Outlook programmieren. Ich meine hier ausdrücklich die "Globale Adressliste" und nicht die Einträge im Kontakte-Ordner, der ist nämlich leer.

Ich habe bereits Zugriff auf die Adressliste und kann die Anzahl der Einträge ermitteln. Außerdem kann ich nach einem Namen suchen und mir z.B. die Informationen Name, Adresse, Typ und ID geben lassen. Das sieht dann in etwa so aus:

Anzahl = 1754
Name: Mustermann Karl
Adresse: /o=XXX/ou=DEXXXXXXXX/cn=Recipients/cn=XX1234
Typ: olUser
ID: <eine lange Zeichenkette aus Zahlen und Buchstaben, ca. 150-200 Zeichen>

Also bis auf Name völlig unbrauchbar. (Warum gibt Adresse nicht die Mail-Adresse zurück ?)

Wie kann ich nun auf die Informationen Name, Abteilung, Telefon, E-Mail (Adresse) zugreifen ?

Mike

17.10.2005 - 18:27 Uhr

Hi masterbell,

wenn Du eine fertiges Control suchst, solltest Du hier mal reinschauen:

http://www.codeproject.com/vb/net/MultiColumnFlatCombo.asp

Du kannst aber die ComboBox auch beim Einlesen deiner Daten füllen, z.B. so:

dataSet.Tabelle.Clear();
DataAdapter.Fill (dataSet.Tabelle);
comboBox.SelectedIndex = -1;
comboBox.Items.Clear();
for (int iPos = 0; iPos < dataSet.Tabelle.Rows.Count; iPos++)
{
  comboBox.Items.Add (new MeineListe (dataSet.Tabelle[iPos]["SPALTE1"].ToString(), 
                                      dataSet.Tabelle[iPos]["SPALTE2"].ToString(), 
                                      dataSet.Tabelle[iPos]["SPALTE3"].ToString(),
                                      Convert.ToInt32 (dataSet.Tabelle[iPos]["SPALTE4"]),
                                      Convert.ToBoolean (dataSet.Tabelle[iPos]["SPALTE5"])));
}

Wichtig dabei ist, daß Du die ComboBox nicht mit einem Dataset oder einer Tabelle verbindest.

Damit das Füllen der ComboBox klappt, verwendest Du noch folgende Klasse:

private class MeineListe
{
  public string Spalte1;
  public string Spalte2;
  public string Spalte3;
  public int    Spalte4;
  public bool   Spalte5;
  public MeineListe (string S1, string S2, string S3, int S4, bool S5)
  {
    this.Spalte1 = S1;
    this.Spalte2 = S2;
    this.Spalte3 = S3;
    this.Spalte4 = S4;
    this.Spalte5 = S5;
  }
  public override string ToString()
  {
    return this.Spalte1 + ", " + this.Spalte2 + ", " + this.Spalte4.ToString();
  }
}

Das Auslesen eines selektierten Listeneintrags funktioniert dann z.B. so:

MeineListe ml = (MeineListe)comboBox.SelectedItem;
label.Text = ml.Spalte3;

Damit kannst Du auf jede Spalte deiner Tabelle zugreifen und kannst auch diverse Datentypen verwenden.

Viel Spaß,
Mike

14.10.2005 - 14:06 Uhr

Hallo,

ich habe da ein SQL-Kommando (Oracle) gefunden, vielleicht kann man das auch verwenden:

select * from tabelle where (to_char(datum,"WW") = "kw")

Für kw muß die Kalenderwoche eingesetzt werden. Der Rest müßte verständlich sein. Die "WW" sind die Formatierung des Datums (Wochen-Nr. eines Jahres).

Ich habe das mal kurz getestet und es hat funktioniert. In MySQL soll es eine ähnliche Funktion geben. Kann ich aber nicht testen.

mfG
Mike

14.10.2005 - 10:53 Uhr

Hallo zusammen,

hier noch ein paar Infos zum Thema Kalenderwochen.

Die Berechnung der Kalenderwochen folgt der ISO-Norm 8601, europaweit umgesetzt in EN 28601, in Deutschland bekannt als DIN 1355. Sinngemäß gilt danach folgendes:
• Eine Kalenderwoche beginnt immer mit einem Montag.
• Die erste Kalenderwoche eines Jahres ist die, in der der vierte Januar liegt.
Somit hat ein Jahr entweder 52 oder 53 Kalenderwochen. Die Tage vor dem 4. Januar können in die letzte Kalenderwoche des Vorjahres fallen, die Tage nach dem 28. Dezember in die erste Kalenderwoche des Folgejahres.

Was den Bug angeht, gibt es noch diese Info:
Nur für manche Tage wird eine falsche Kalenderwoche berechnet (30.12.2002 ergibt KW 53, obwohl nach Norm KW 1 richtig wäre). Microsoft hat den Fehler in der Knowledgbase Q200299 auch dokumentiert, war aber bisher nicht in der Lage, den Fehler zu beheben. Der Fehler befindet sich in der Datei "Oleaut32.dll" und die wird von vielen Windows-Komponenten benutzt. Was das heißt, kann sich jeder denken (alle Programme, alle Plattformen). Aber komisch ist z.B., daß Outlook keinen Fehler macht. War da ein MS-Programmierer schlauer als Bill ?

mfG
Mike

14.10.2005 - 09:12 Uhr

Hallo Coven,

soweit ich weiß, ist die Kalenderwoche 1 immer die Woche, in der der 4. Januar "stattfindet". Damit gilt:


DateTime vierterJanuar = new DateTime (Jahr, 1, 4);

Über die Funktion DateTime.DayOfWeek erhält Du dann den Wochentag (0 für Sonntag bis 6 für Samstag). Bei Verwendung von


int woTag4J = (((int)vierterJanuar.DayOfWeek + 6) % 7) + 1;

sollte dann 1 für Montag bis 7 für Sonntag rauskommen.

Jetzt sollte es für Dich nicht mehr schwer sein, das Datum von Montag und Sonntag zu errechnen. Für eine beliebige Kalenderwoche mußt Du dann nur noch n-mal 7 Tage addieren/abziehen, ganz einfach.

Übrigens gibt es auch eine Funktion GetWeekOfYear in den CultureInfos. Vielleicht schaust Du Dir das mal genauer an. Aber Vorsicht, die Funktion enthält einen kleinen Bug. Manchmal gibt die Funktion eine KW 53 zurück und macht gleich mit der KW 2 weiter. Das Problem habe ich so gelöst:


int CalendarWeek (DateTime dtDate)
{
  CultureInfo myCI = new CultureInfo("de-DE");
  Calendar myCal = myCI.Calendar;

  int iWeek = myCal.GetWeekOfYear (dtDate, myCI.DateTimeFormat.CalendarWeekRule, myCI.DateTimeFormat.FirstDayOfWeek);
  int iNextWeek = myCal.GetWeekOfYear (dtDate.AddDays(7), myCI.DateTimeFormat.CalendarWeekRule, myCI.DateTimeFormat.FirstDayOfWeek);

  if (iWeek > 52)
  {
    if (iNextWeek == 2)
    {
      iWeek = 1;
    }
  }

  return iWeek;
}

Aber das wirklich nur nebenbei.

mfG
Mike

13.10.2005 - 13:11 Uhr

Hallo FZelle,

Daß das Paßwort nicht im Klartext abgespeichert wird, versteht sich von selbst. Und dafür reicht auch eine einfache Routine zum Verschlüsseln aus.

Es ging eigentlich nur darum, eine neue Spalte, die erst zur Laufzeit entsteht, an einer beliebigen Position im Datagrid anzuzeigen. Und das klappt jetzt auch (siehe Code).

Mike

13.10.2005 - 08:15 Uhr

Hallo Programmierhans,

darüber könnte man sich länger unterhalten. Ich will also mal beschreiben, um was es geht.

Für die Benutzung des Programms ist es sehr wichtig zu wissen, wer wann welche Daten bearbeitet. Nach dem Programmstart sollen sich alle Benutzer des Programms identifizieren mit Name oder Personal-Nr. und einem persönlichen Paßwort. Bei der ersten Anmeldung muß der Benutzer sein Paßwort festlegen. Für den Fall, daß der Benutzer sein Paßwort einmal vergißt, soll der Programm-Administrator die Möglichkeit haben, daß eingetragene Paßwort zu löschen. Das Paßwort selbst wird nie im Programm angezeigt. Es soll nur dargestellt werden, ob der Benutzer ein Paßwort eingetragen hat. Die (Benutzer-)Datenbank selbst enthält nur ein Datenfeld PASSWORT (VarChar2), aber kein Kennzeichen, ob ein Paßwort existiert (das macht auch keinen Sinn). Deshalb brauche ich im DatenGrid eine Spalte mit einer CheckBox. Diese Spalte wird dem DataSet erst zur Laufzeit hinzugefügt, leider aber am Ende. Dementsprechend sieht man die Spalte auch im DataGrid erst ganz rechts, weit außerhalb des Bildschirms (das DataGrid hat 16 Spalten, ohne das Paßwortfeld). Mein Code sorgt nun dafür, daß die Spalte mit der CheckBox in den sichtbaren Bereich des DataGrids kommt, ohne nach rechts zu scrollen. In den TableStyles kann ich die Spalte im Designer noch nicht berücksichtigen, weil sie da einfach noch nicht existiert.

Ich hoffe, Du verstehst jetzt, um was es mir ging.

mfG
Mike

12.10.2005 - 18:25 Uhr

Hallo,
jetzt habe ich das DataGrid so, wie ich es habe will. Für alle hier nochmal der Code:


private void Form1_Load(object sender, System.EventArgs e)
{
  dataSet1.USERTABLE.Clear();

  // eine neue Spalte vom Typ BOOL erstellen
  DataColumn newCol = new DataColumn ("PW", typeof(bool));
  // den Ausdruck für die neue Spalte "berechnen"
  newCol.Expression = "IIF (PASSWORT <> '.', true, false)";
  // und die Spalte an das DataSet anhängen
  dataSet1.USERTABLE.Columns.Add (newCol);

  // den Style für die neue Spalte setzen
  DataGridBoolColumn dgtb = new DataGridBoolColumn();
  dgtb.HeaderText = "Paßwort";
  dgtb.MappingName = "PW";
  dgtb.AllowNull = false;

  // ein neues TableStyle erstellen und mappen
  DataGridTableStyle newTS = new DataGridTableStyle();
  newTS.MappingName = dataGrid1.TableStyles[0].MappingName;

  // den neuen TableStyle mit Werten des alten TableStyle füllen
  for (int j=0; j<dataGrid1.TableStyles[0].GridColumnStyles.Count; j++)
  {
    // ... und an der 5. Position die neue Spalte dazu nehmen
    if (j == 5)
    {
      newTS.GridColumnStyles.Add (dgtb);
    }
    newTS.GridColumnStyles.Add (dataGrid1.TableStyles[0].GridColumnStyles[j]);
  }

  dataGrid1.TableStyles.Clear();
  dataGrid1.TableStyles.Add (newTS);

  oracleDataAdapter1.Fill (dataSet1.USERTABLE);
}

So funktioniert das.

Mike

12.10.2005 - 08:46 Uhr

Hallo,
natürlich kann ich auch gleich TableStyles verwenden. Das habe ich jetzt auch mal getan. Die Spalte PASSWORT habe ich auf WIDTH=0 gesetzt (ich hatte eigentlich erartet, daß ich dann zur Laufzeit die Spalte aufziehen kann, ist aber zum Glück nicht passiert). Ich muß jetzt nur noch dem Dataset und den TableStyles die neue Spalte zuweisen. Sieht dann ungefähr so aus:


...
      DataColumn newCol = new DataColumn ("PW", typeof(bool));
      newCol.Expression = "IIF (PASSWORT <> '.', true, false)";
      dataSet1.USERTABLE.Columns.Add (newCol);

      DataGridBoolColumn dgtb = new DataGridBoolColumn();
      dgtb.HeaderText = "Paßwort";
      dgtb.MappingName = "PW";
      dgtb.AllowNull = false;
      dataGridTableStyle1.GridColumnStyles.Add (dgtb);
...

Jetzt steht die neue Spalte auch im DataGrid, aber an letzter Stelle. Wie bringe ich aber die neue Spalte an die 5. Position im DataGrid ?

11.10.2005 - 17:59 Uhr

Hallo,

Ich habe eine Oracle-Tabelle für eine Benutzer-Verwaltung. Die Tabelle enthält u.a. ein Textfeld PASSWORT. Im Programm soll die Tabelle in einem DataGrid angezeigt und bearbeitet werden. Die Spalte PASSWORT soll nicht sichtbar sein. Dafür will ich aber eine Spalte anzeigen, die anzeigt, ob der Benutzer ein Paßwort hat oder nicht (z.B. mit einer Checkbox). Ich verwende (vorerst) für das DataGrid keine TableStyles im Designer. Nach einigen Versuchen habe ich jetzt folgenden Code:


private void Form1_Load(object sender, System.EventArgs e)
{
  dataSet1.USERTABLE.Clear();

  // die Anzahl der Tabellenspalten merken
  int nCols = dataSet1.USERTABLE.Columns.Count;

  // eine neue Spalte vom Typ BOOL erstellen
  DataColumn newCol = new DataColumn ("PW", typeof(bool));
  // den Ausdruck für die neue Spalte "berechnen"
  newCol.Expression = "IIF (PASSWORT <> '.', true, false)";
  // und die Spalte an das DataSet anhängen
  dataSet1.USERTABLE.Columns.Add (newCol);

  // ein neues TableStyle erstellen und mappen
  DataGridTableStyle newTS = new DataGridTableStyle();
  newTS.MappingName = dataGrid1.DataMember;

  // lokale Variablen für die GridColumnStyles (gcs...)
  DataGridTextBoxColumn gcsText;
  DataGridBoolColumn gcsBool;

  for (int i = 0; i < nCols; ++i)
  {
    if (i != 5) // an der 5. Position soll die Spalte PASSWORT ausgetauscht werden
    {
      // die bisherigen Spalten in das neu TableStyle übernehmen
      if (dataSet1.USERTABLE.Columns[i].DataType == typeof(bool))
      {
        gcsBool = new DataGridBoolColumn();
        gcsBool.HeaderText = dataSet1.USERTABLE.Columns[i].ColumnName;
        gcsBool.MappingName = dataSet1.USERTABLE.Columns[i].ColumnName;
        newTS.GridColumnStyles.Add (gcsBool);
      }
      else
      {
        gcsText = new DataGridTextBoxColumn();
        gcsText.HeaderText = dataSet1.USERTABLE.Columns[i].ColumnName;
        gcsText.MappingName = dataSet1.USERTABLE.Columns[i].ColumnName;
        newTS.GridColumnStyles.Add (gcsText);
      }
    }
    else
    {
      // die neue Spalte an der 5. Position in das neu TableStyle übernehmen
      DataGridBoolColumn dgtb = new DataGridBoolColumn();
      dgtb.HeaderText = "Passwort";
      dgtb.MappingName = "PW";
      newTS.GridColumnStyles.Add (dgtb);
    }
  }

  dataGrid1.TableStyles.Clear();
  dataGrid1.TableStyles.Add (newTS);
      
  oracleDataAdapter1.Fill (dataSet1.USERTABLE);
} 

Für den Anfang funktioniert das schon ganz gut. Prinzipiell müßte das auch funktionieren, wenn ich die neue Spalte nur einfach im DataGrid an einer beliebigen Spalte einfügen will.

Mich würde nun interessieren, was Ihr davon haltet. Gibt es vielleicht noch bessere Lösungen ?

mfG
Mike

06.10.2005 - 15:52 Uhr

Vielleicht hilft Dir das:

Es gibt eine Konstante "Convert.DBNull", die eine Datenbankspalte ohne Daten darstellt, als eine sogenannte Datenbank-NULL.

Beispiel:
Row["DATUM"] = Convert.DBNull;

Ich verwende das immer, wenn ich eine NULL im Datenbankfeld haben will. Klappt hervorragend.

mfG
Mike

05.10.2005 - 15:04 Uhr

Hallo skytwister,

ich kann Dir zwar (noch) kein Beispiel geben, aber vielleicht funktioniert der folgende Ansatz.

Wenn Du im Windows Explorer eine PDF-Datei mit der rechten Maustaste anklickst, bekommst Du u.a. den Menüpunkt "drucken" angezeigt. Versuche doch einfach, es auch so zu machen. Starte in deinem Programm den AcrobatReader mit folgenden Parametern:

"C:\Program Files\Adobe\Acrobat 5.0\Reader\AcroRd32.exe" /p /h "PDF-File.pdf"

Der Parameter /p sorgt dafür, dass die PDF-Datei gedruckt wird.
Der Parameter /h sorgt dafür, dass der Drucken-Dialog nicht angezeigt wird.

Ich habe das mal mit einer kleinen Batchdatei ausprobiert. Das hat ganz gut funktioniert. Allerdings bleibt der AcrobatReader danach mit einem leeren Fenster stehen und die Batchdatei wartet auf das Ende des AcrobatReaders. Da habe ich aber noch keine Lösung dafür.

Mike

04.10.2005 - 18:07 Uhr

Hallo,
da habe ich schon wieder ein Problem.
Ich habe 2 Tabellen mit folgender (verkürzten) Struktur:

Tabelle 1 - Name, Kennung, Telefon, Mailadresse
Tabelle 2 - Kennung, Artikel, Hersteller, Datum

Ich will eine Auswertung mit Crystal Reports machen. Der Report besitzt eine Gruppe (Feld "Kennung"). Bei jeder Änderung des Feld "Kennung" soll eine neue Seite beginnen und es sollen, nach Datum sortiert, alle Artikel aufgelistet werden. Ich habe im Report eine Beziehung zwischen beiden Tabellen hergestellt. Das funktioniert inzwischen auch ganz gut.

Und jetzt das Problem: Bei jeder neuen "Kennung" soll die entsprechende Seite (oder Seiten) an die zugehörige Mailadresse versendet werden. Als Zwischenstufe wären PDF-Files möglich, die kann ich dann einer Mail als Anhang mitgeben. Dann müßte ich aber wissen, welche Kennung der Report enthält. Die Mailadresse läßt sich dann ja aus der Tabelle holen. Wie kann ich Crystal Reports veranlassen, für jede neue "Kennung" ein PDF-File zu erstellen und mir die Kennung zu geben ? Geht das mit Crystal Reports überhaupt ? Soweit ich weiß, kann ich nur ganze Reports als PDF-File erstellen und von Rückgabewerten habe ich noch nichts gelesen.

Hat jemand dazu eine gute Idee ?

Mike

04.10.2005 - 17:08 Uhr

Also ich habe mir überlegt, es mit einer UserControl zu versuchen. Irgendwann muß ich ja mal damit anfangen (mit den UserControls) und das wäre doch die passende Gelegenheit.

Aber nun muß ich feststellen, daß DarkAngel76 schneller war als ich. Hätte mich auch ehrlich gewundert, wenn ich der Erste sein sollte, der einen Monat "zählen" will. Also besten Dank für die Anregung von DarkAngel76. Ich werde es ausprobieren. Mein UserControl kann ich ja immer noch schreiben.

Bis zum nächsten Problem ...

Mike

30.09.2005 - 12:21 Uhr

Hallo herbivore,
ja, ich habe bisher eben auch nichts gefunden. Jetzt überlege ich sogar, ob ich mir nicht ein eigenes Control bauen sollte. Aber ich werde wohl erst mal ein Wochenende drüber schlafen. Also, schönes WE und bis demnächst
Mike

29.09.2005 - 18:17 Uhr

Hallo,
ich habe auf einer Form einen DateTimePicker gesetzt und u.a. folgende Eigenschaften gesetzt:
Format = Custom
ShowUpDown = True
CustonFormat = "MMMM yyyy"
Aufgabe des Controls ist es, beim Anklicken der Buttons UP und DOWN Monat und Jahr zusammen hoch bzw. runter zu zählen, also auch bei einem Jahreswechsel (Dezember 2005 --> Januar 2006 / Januar 2005 --> Dezember 2004). Leider wird aber nur der Monat oder nur das Jahr gezählt, aber nicht beide zusammen. Ich habe bisher auch noch kein Ereignis gefunden, mit dem ich auf die Buttons getrennt reagieren kann. Gibt es dafür eine Lösung ?

PS: Habe das Problem gestern offensichtlich ins falsche Forum (Web- und Netzwerktechnologien) gestellt. Vielleicht kann das dort Einer löschen ?

mfG
Mike

28.09.2005 - 09:35 Uhr

Hallo,
ich habe auf einer Form einen DateTimePicker gesetzt und u.a. folgende Eigenschaften gesetzt:
Format = Custom
ShowUpDown = True
CustonFormat = MMMM yyyy
Aufgabe des Controls ist es, beim Anklicken der Buttons UP und DOWN Monat und Jahr zusammen hoch bzw. runter zu zählen, also auch bei einem Jahreswechsel (Dezember 2005 --> Januar 2006 / Januar 2005 --> Dezember 2004). Leider wird aber nur der Monat oder nur das Jahr gezählt, aber nicht beide zusammen. Ich habe bisher auch noch kein Ereignis gefunden, mit dem ich auf die Buttons getrennt reagieren kann. Gibt es dafür eine Lösung ?

[EDIT]
Das Thema befindet sich jetzt hier.
[/EDIT]